function varargout = TLFunctionDlg(action,varargin)

% TL_FUNCTION_DLG manages the user interface for TargetLink Function block
%
% SYNTAX dlgInfo = TLFunctionDlg('GetDlgInfo');
%   gets dialog info of TargetLink Function block
%
%   INPUT ARGUMENTS
%   - / -
%
%   OUTPUT ARGUMENTS
%   dlgInfo         dialog information contains pageNames etc.
%
% SYNTAX [sheetDims,ctrlPos] = TLFunctionDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLFunctionDlg('Create', pageName, dlgfig, dlgdata);
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata, bModified] = TLFunctionDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX [dlgdata,bModified] = TLFunctionDlg('Update', dlgfig, dlgdata, pageNum);
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLFunctionDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_UtilityBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.53 $
% $Date: 2011/09/02 08:49:09MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


% branch depending on action
switch action,
    
    case 'GetDlgInfo'
        hBlock = varargin{1};
        dlgInfo = tl_get_dlginfodefaults('tlutil');
        titleName = 'Function';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName(1:end-numel(pathinfo.name)-1));
        % return structure holding the names of tabs
        dlgInfo.pageNames = { ...
            'Options'; ...
            'Arguments'; ...
            'Incremental'; ...
            'AUTOSAR'; ...
            'Documentation'};
        % icon of switch for dual edit of output and AUTOSAR data
        dlgInfo.bDualEdit = 1;
        % mainData = get_tlcg_data(bdroot(hBlock));
        mainData = tl_handle_main_data('get', bdroot(hBlock));
        % initialise extended data
        if ~isempty(mainData)
            dlgInfo.extdata.codegenmode = mainData.codegenerationmode;
        else
            dlgInfo.extdata.codegenmode = 0;
        end
        dlgInfo.extdata.bIsEditMode = false;
        tlData = get_tlcg_data(hBlock);
        % set defaultPageNum to AUTOSAR page if AUTOSAR is enabled
        if (tlData.autosar.isrunnable || tlData.autosar.isoperationcall) && any(dlgInfo.extdata.codegenmode == [0 2])
            dlgInfo.defaultPageNum = 4;
        else
            dlgInfo.defaultPageNum = 1;
        end
        varargout{1} = dlgInfo;
        varargout{2} = tlData;
        
    case 'CtrlPositions',
        % call function which handles different pages
        [sheetDims, ctrlPos] = FcnGeneralCtrlPositions(varargin{1}, varargin{2}, varargin{4});
        varargout{1} = sheetDims;
        varargout{2} = ctrlPos;
        
    case 'Create'
        % call function which handles different pages
        dlgdata = FcnCreateGeneral(varargin{1}, varargin{2}, varargin{3});
        varargout{1} = dlgdata;
        
    case 'Manage'
        % call function which handles different pages
        [dlgdata, bModified] = FcnManageGeneral(varargin{1}, varargin{2}, varargin{3}, varargin{4});
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'ManageSystemIcons',
        dlgfig     = varargin{1};
        dlgdata    = varargin{2};
        pageAction = varargin{3};
        [dlgdata, bModified] = FcnManageSystemIcons(dlgfig,dlgdata,pageAction);
        varargout{1} = dlgdata;
        varargout{2} = bModified;
        
    case 'Update'
        dlgfig    = varargin{1};
        dlgdata   = varargin{2};
        pageNum   = varargin{3};
        dlgdata = FcnUpdateGeneral(dlgfig, dlgdata, pageNum);
        varargout{1} = dlgdata;
        
    case 'Apply'
        dlgdata  = varargin{2};
        bClose   = varargin{3};
        [dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);
        varargout{1} = dlgdata;
        varargout{2} = bClose;
        
    otherwise
        error(['Invalid action: "' action '"']);
        
end; %switch


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manages actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        codeFile = get_codefile(dlgdata.model);
        if exist(codeFile, 'file'),
            codeedit(codeFile);
        end
        
    case 'ViewCode'
        tl_create_links_to_model('ShowCodeViewFile',dlgdata.model);
        
    case 'DualEdit'
        dlgdata.extdata.bIsEditMode = strcmp(get(dlgdata.SystemButtons.DualEdit, 'State'), 'on');
        bModified = true;
        
    otherwise
        error('Invalid callback');
        
end % switch(action)


%-------------------------------------------------------------------------------
% FcnGeneralCtrlPositions handles "Control Positions" call for the different pages of the dialog
%
% INPUT ARGUMENTS
%   pageName        name of the page
%   commonGeom      common Geometries like text size, ...
%   sheetDims       sheetDims
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%-------------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnGeneralCtrlPositions(pageName, commonGeom, sheetDims)
switch pageName,
    case 'Options',
        [sheetDims,ctrlPos] = FcnOptionsCtrlPositions(commonGeom, sheetDims);
    case 'Arguments'
        [sheetDims,ctrlPos] = FcnArgumentsCtrlPositions(commonGeom, sheetDims);
    case 'Incremental'
        [sheetDims,ctrlPos] = FcnIncrementalCtrlPositions(commonGeom, sheetDims);
    case 'AUTOSAR'
        [sheetDims,ctrlPos] = FcnAutosarCtrlPositions(commonGeom, sheetDims);
    case 'Documentation'
        bTblBlock = 0;
        bCodeComment = 1;
        [sheetDims,ctrlPos] = ...
            TLManageDocCtrls('ctrlpos',commonGeom,sheetDims,bCodeComment,bTblBlock);
    otherwise
        error(['Nonexistent page ''' action'''']);
end; %switch
% end of function FcnGeneralCtrlPositions


%-------------------------------------------------------------------------------
% FcnCreateGeneral handles "Create" call for the different pages of the dialog
%
% INPUT ARGUMENTS
%   pageName    name of the page
%   dlgfig      handle of dialgo figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-------------------------------------------------------------------------------
function  dlgdata = FcnCreateGeneral(pageName, dlgfig, dlgdata)

pageNum  = strcmp(pageName,dlgdata.pageNames);
% branch depending on page name
switch pageName
    case 'Options'
        dlgdata = FcnCreateOptionsPage(pageNum,dlgfig,dlgdata);
    case 'Arguments'
        dlgdata = FcnCreateArgumentsPage(pageNum,dlgfig,dlgdata);
    case 'Incremental'
        dlgdata = FcnCreateIncrementalPage(pageNum,dlgfig,dlgdata);
    case 'AUTOSAR'
        dlgdata = FcnCreateAutosarPage(pageNum,dlgfig,dlgdata);
    case 'Documentation'
        dlgdata =  TLManageDocCtrls('create',pageNum,dlgfig,dlgdata);
    otherwise
        error(['Nonexistent page ''' action'''']);
end; %switch
dlgdata.pageData{pageNum}.ctrlPos = [];
% end of function FcnCreateGeneral


%-------------------------------------------------------------------------------
% FcnManageGeneral handles "Manage" call for the different pages of the dialog
%
% INPUT ARGUMENTS
%   pageName        name of the page
%   dlgfig          handle of dialgo figure
%   dlgdata         dialog data
%   pageAction      dependend of the control that has been changed on the page
%
% OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       1 if data has been modified, zero otherwise
%-------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageGeneral(pageName, dlgfig, dlgdata, pageAction)
% branch depending on page name
pageNum    = strcmp(pageName,dlgdata.pageNames);
switch pageName
    case 'Options'
        [dlgdata,bModified] = FcnManageOptionsPage(pageNum,dlgfig,dlgdata,pageAction);
    case 'Arguments'
        [dlgdata,bModified] = FcnManageArgumentsPage(pageNum,dlgfig,dlgdata,pageAction);
    case 'Incremental'
        [dlgdata,bModified] = FcnManageIncrementalPage(pageNum,dlgfig,dlgdata,pageAction);
    case 'AUTOSAR'
        [dlgdata,bModified] = FcnManageAutosarPage(pageNum,dlgdata,pageAction);
    case 'Documentation'
        [dlgdata,bModified] = ...
            TLManageDocCtrls('callback',pageNum,dlgfig,dlgdata,pageAction);
    otherwise
        error(['Nonexistent page ''' action'''']);
end; %switch
% end of function FcnManageGeneral


%%------------------------------------------------------------------------------
% FcnUpdateGeneral handles "Update" call for the different pages of the dialog
%
% INPUT ARGUMENTS
%   dlgfig       handle of dialog figure
%   dlgdata      dialog data
%   pageNum      number of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-------------------------------------------------------------------------------
function dlgdata = FcnUpdateGeneral(dlgfig, dlgdata, pageNum)

pageName = dlgdata.pageNames{pageNum};
% branch depending on page name
switch pageName
    case 'Options'
        FcnUpdateOptionsPage(dlgfig,dlgdata,pageNum);
    case 'Arguments'
        FcnUpdateArgumentsPage(dlgfig,dlgdata,pageNum)
    case 'Incremental'
        FcnUpdateIncrementalPage(dlgfig,dlgdata,pageNum);
    case 'AUTOSAR'
        dlgdata = FcnUpdateAutosarPage(dlgfig,dlgdata,pageNum);
    case 'Documentation'
        TLManageDocCtrls('update',pageNum,dlgfig,dlgdata);
    otherwise
        error(['Nonexistent page ''' action'''']);
end; %switch
% end of function FcnCreateGeneral


%===============================================================================
%
%                                 Options Page
%
%===============================================================================
%-------------------------------------------------------------------------------
% FcnOptionsCtrlPosition calculates positions for all controls on option page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%   sheetDims       dimension of sheet
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnOptionsCtrlPositions(commonGeom,sheetDims)

% Get the sizes of the edit fields, checkboxes, buttons and labels (last is
% determined from the longest label).
strings_and_styles = {
    'Make function reusable:',  'checkbox'; ...
    'Restart function name:',   'text'; ...
    repmat('m',1,30),           'edit'; ...
    'n',                        'pushbutton'; ...
    'Force',                    'checkbox'};
[reuseFcnCheckboxSize, ...
    labelSize, ...
    editSize, ...
    dotPushButtonSize, ...
    forceCheckboxSize] = ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% correct height, because on some platforms icon overlapped button boundary; icon height is 18 pixel.
dotPushButtonSize(2) = max(22, dotPushButtonSize(2));

% Get the page partitioning and row/column spacing.
widths = [labelSize(1) editSize(1) forceCheckboxSize(1)];
[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

dotButtonSize = [2*dotPushButtonSize(1) dotPushButtonSize(2)];

% All groupboxes in this page have the same width, which is the maximum of
% the 'needed' width and the size of the page.
OptGroupboxWidth = sum(colWidth) + 2/3 * colDelta + 2 * commonGeom.frameSideEdgeBuffer;
OptGroupboxWidth = max(OptGroupboxWidth, ...
    sheetDims(1) - 2 * commonGeom.frameSideEdgeBuffer);

% Position of code file options groupbox.
codeFileOptGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + 3 * editSize(2) + 2 * rowDelta ...
    + commonGeom.frameBottomEdgeBuffer;
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + commonGeom.sheetBottomEdgeBuffer;
ctrlPos.codeFileOptGroupbox = [cx,cy,OptGroupboxWidth,codeFileOptGroupboxHeight];

% Postion of "Link external code" label.
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.linkExtCodeCheckbox = [cx cy reuseFcnCheckboxSize];

% Position of module label, edit and browse.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.moduleLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.moduleEdit = [cx cy editSize];
% select button
cx = col(3);
ctrlPos.moduleSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.moduleMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

% Position of "code file name" label and edit field.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.cFileLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.cFileEdit = [cx cy editSize];

% Position of code options groupbox.
codeOptGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + 11 * editSize(2) + 10 * rowDelta ...
    + commonGeom.frameBottomEdgeBuffer;
cx = ctrlPos.codeFileOptGroupbox(1);
cy = ctrlPos.codeFileOptGroupbox(2) + codeFileOptGroupboxHeight...
    + commonGeom.textHeight;
ctrlPos.codeOptGroupbox =  [cx,cy,OptGroupboxWidth,codeOptGroupboxHeight];

% Position of "make functions reusable" checkbox.
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.reuseFcnCheckbox = [cx cy reuseFcnCheckboxSize];

% Position of "Subsystem ID" Label and Edit field
cy = cy + reuseFcnCheckboxSize(2) + rowDelta;
ctrlPos.subsystemIDLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.subsystemIDEdit = [cx cy editSize];

% Position of "Term Function class" label, edit and browse.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.termFcnClassLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.termFcnClassEdit = [cx cy editSize];
% select button
cx = col(3);
ctrlPos.termFcnClassSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.termFcnClassMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

%  Position of "Term Function name" label, edit and force checkbox.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.termFcnNameLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.termFcnNameEdit = [cx cy editSize];
cx = col(3);
ctrlPos.termFcnNameForce = [cx cy forceCheckboxSize];

% Position of "Init Function class" label, edit and browse.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.initFcnClassLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.initFcnClassEdit = [cx cy editSize];
% select button
cx = col(3);
ctrlPos.initFcnClassSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.initFcnClassMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

%  Position of "Init Function name" label, edit and force checkbox.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.initFcnNameLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.initFcnNameEdit = [cx cy editSize];
cx = col(3);
ctrlPos.initFcnNameForce = [cx cy forceCheckboxSize];

% Position of "Restart Function class" label, edit and browse.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.restartFcnClassLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.restartFcnClassEdit = [cx cy editSize];
% select button
cx = col(3);
ctrlPos.restartFcnClassSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.restartFcnClassMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

%  Position of "Restart Function name" label, edit and Force checkbox.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.restartFcnNameLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.restartFcnNameEdit = [cx cy editSize];
cx = col(3);
ctrlPos.restartFcnNameForce = [cx cy forceCheckboxSize];

% Position of "Step Function class" label, edit and browse.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.stepFcnClassLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.stepFcnClassEdit = [cx cy editSize];
% select button
cx = col(3);
ctrlPos.stepFcnClassSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.stepFcnClassMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

%  Position of "Step Function name" label, edit and force checkbox.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.stepFcnNameLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.stepFcnNameEdit = [cx cy editSize];

% Position of "Description" label and edit field.
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.descLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.fcnDescEdit = [cx cy editSize];

% Width and height of page.
width = OptGroupboxWidth + 2 * commonGeom.sheetSideEdgeBuffer;
height = ...
    + ctrlPos.codeFileOptGroupbox(4) ...
    + ctrlPos.codeOptGroupbox(4) ...
    + 2 * (commonGeom.textHeight + rowDelta) ...
    + commonGeom.sheetBottomEdgeBuffer;

% message of dual edit mode
textWidth = ctrlPos.codeOptGroupbox(3);
textHeight = 2 * commonGeom.textHeight;

cx = col(1) - commonGeom.frameSideEdgeBuffer;
cy = ctrlPos.codeOptGroupbox(2) + ctrlPos.codeOptGroupbox(4) ...
    + commonGeom.textHeight;

% text frame
ctrlPos.dualEditText = [cx ,cy, textWidth, textHeight];

sheetDims = [width height+textHeight];
% end of function FcnOptionsCtrlPositions


%-------------------------------------------------------------------------------
% FcnCreateOptionsPage creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of the page
%   dlgfig      handle of dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%
% HINT:
% Edit fields and checkboxes are left empty,
% they are filled out with the block data in the update function.
%-------------------------------------------------------------------------------
function dlgdata = FcnCreateOptionsPage(pageNum,dlgfig,dlgdata)

ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};
defColor = get(0, 'DefaultUIControlBackgroundColor');

userDataMenuButton.cDataEnabled  = tl_get_icon('ArrowHeadDown_10x18', 'BackgroundColor', defColor);
userDataMenuButton.cDataDisabled = tl_get_icon('ArrowHeadDown_10x18_disabled');
userDataSelectButton.cDataEnabled  = tl_get_icon('Browse_Seperator_24x18', 'BackgroundColor', defColor);
userDataSelectButton.cDataDisabled = tl_get_icon('Browse_Seperator_24x18');

% Code options groupbox
Children.codeOptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Code options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.codeOptGroupbox);

% create dualEditText
Children.dualEditText = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   ' ', ...
    'Position', ctrlPos.dualEditText);

% Description
Children.descLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Description:', ...
    'Position', ctrlPos.descLabel);

Children.fcnDescEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.fcnDescEdit);

% Step fcn name
Children.stepFcnNameLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Step function name:', ...
    'Position', ctrlPos.stepFcnNameLabel);

Children.stepFcnNameEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.stepFcnNameEdit);

% Step fcn class
Children.stepFcnClassLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Step function class:', ...
    'Position', ctrlPos.stepFcnClassLabel);

Children.stepFcnClassEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.stepFcnClassEdit);

Children.stepFcnClassSelectButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.stepFcnClassSelectButton);

Children.stepFcnClassMenuButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.stepFcnClassMenuButton);

stepCMenu = uicontextmenu('Parent', dlgfig);
set(Children.stepFcnClassEdit, 'UIContextMenu', stepCMenu);
set(Children.stepFcnClassMenuButton, 'UIContextMenu', stepCMenu);
menu.select = uimenu(stepCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''stepFcnClassSelectButton'')',pageName));
menu.edit = uimenu(stepCMenu, ...
    'Label', 'Edit', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''stepFcnEditDDObject'')',pageName), ...
    'Separator','on');
menu.show = uimenu(stepCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''stepFcnShowDDObject'')',pageName), ...
    'Separator','on');
set(stepCMenu, 'UserData', menu);

% Restart fcn name
Children.restartFcnNameLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Restart function name:', ...
    'Position', ctrlPos.restartFcnNameLabel);

Children.restartFcnNameEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.restartFcnNameEdit);

Children.restartFcnNameForce = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'checkbox', ...
    'String',   'Force', ...
    'Position', ctrlPos.restartFcnNameForce);

% Restart fcn class
Children.restartFcnClassLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Restart function class:', ...
    'Position', ctrlPos.restartFcnClassLabel);

Children.restartFcnClassEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.restartFcnClassEdit);

Children.restartFcnClassSelectButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.restartFcnClassSelectButton);

Children.restartFcnClassMenuButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.restartFcnClassMenuButton);

restartCMenu = uicontextmenu('Parent', dlgfig);
set(Children.restartFcnClassEdit, 'UIContextMenu', restartCMenu);
set(Children.restartFcnClassMenuButton, 'UIContextMenu', restartCMenu);
menu.select = uimenu(restartCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''restartFcnClassSelectButton'')',pageName));
menu.edit = uimenu(restartCMenu, ...
    'Label', 'Edit', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''restartFcnEditDDObject'')',pageName), ...
    'Separator','on');
menu.show = uimenu(restartCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''restartFcnShowDDObject'')',pageName), ...
    'Separator','on');
set(restartCMenu, 'UserData', menu);

% Init fcn name
Children.initFcnNameLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Init function name:', ...
    'Position', ctrlPos.initFcnNameLabel);

Children.initFcnNameEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.initFcnNameEdit);

Children.initFcnNameForce = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'checkbox', ...
    'String',   'Force', ...
    'Position', ctrlPos.initFcnNameForce);

% Init fcn class
Children.initFcnClassLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Init function class:', ...
    'Position', ctrlPos.initFcnClassLabel);

Children.initFcnClassEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.initFcnClassEdit);

Children.initFcnClassSelectButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.initFcnClassSelectButton);

Children.initFcnClassMenuButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.initFcnClassMenuButton);

initCMenu = uicontextmenu('Parent', dlgfig);
set(Children.initFcnClassEdit, 'UIContextMenu', initCMenu);
set(Children.initFcnClassMenuButton, 'UIContextMenu', initCMenu);
menu.select = uimenu(initCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''initFcnClassSelectButton'')',pageName));
menu.edit = uimenu(initCMenu, ...
    'Label', 'Edit', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''initFcnEditDDObject'')',pageName), ...
    'Separator','on');
menu.show = uimenu(initCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''initFcnShowDDObject'')',pageName), ...
    'Separator','on');
set(initCMenu, 'UserData', menu);

% Term fcn name
Children.termFcnNameLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Term function name:', ...
    'Position', ctrlPos.termFcnNameLabel);

Children.termFcnNameEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.termFcnNameEdit);

Children.termFcnNameForce = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'checkbox', ...
    'String',   'Force', ...
    'Position', ctrlPos.termFcnNameForce);

% Term fcn class
Children.termFcnClassLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Term function class:', ...
    'Position', ctrlPos.termFcnClassLabel);

Children.termFcnClassEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.termFcnClassEdit);

Children.termFcnClassSelectButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.termFcnClassSelectButton);

Children.termFcnClassMenuButton = uicontrol( ...
    'Parent',            Children.codeOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.termFcnClassMenuButton);

termCMenu = uicontextmenu('Parent', dlgfig);
set(Children.termFcnClassEdit, 'UIContextMenu', termCMenu);
set(Children.termFcnClassMenuButton, 'UIContextMenu', termCMenu);
menu.select = uimenu(termCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''termFcnClassSelectButton'')',pageName));
menu.edit = uimenu(termCMenu, ...
    'Label', 'Edit', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''termFcnEditDDObject'')',pageName), ...
    'Separator','on');
menu.show = uimenu(termCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''termFcnShowDDObject'')',pageName), ...
    'Separator','on');
set(termCMenu, 'UserData', menu);

% Subsystem ID
Children.subsystemIDLabel = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Subsystem ID:', ...
    'Position', ctrlPos.subsystemIDLabel);

Children.subsystemIDEdit = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.subsystemIDEdit);

Children.reuseFcnCheckbox = uicontrol( ...
    'Parent',   Children.codeOptGroupbox, ...
    'Style',    'checkbox', ...
    'String',   'Make function reusable', ...
    'Position', ctrlPos.reuseFcnCheckbox);

% Code file options groupbox
Children.codeFileOptGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Code file options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.codeFileOptGroupbox);

% code file name
Children.cFileLabel  = uicontrol( ...
    'Parent',             Children.codeFileOptGroupbox, ...
    'Style',              'text', ...
    'String',             'C code file name:', ...
    'Position',           ctrlPos.cFileLabel );

Children.cFileEdit  = uicontrol( ...
    'Parent',             Children.codeFileOptGroupbox, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.cFileEdit );

% module
Children.moduleLabel = uicontrol( ...
    'Parent',   Children.codeFileOptGroupbox, ...
    'Style',    'text', ...
    'String',   'Module:', ...
    'Position', ctrlPos.moduleLabel);

Children.moduleEdit = uicontrol( ...
    'Parent',   Children.codeFileOptGroupbox, ...
    'Style',    'edit', ...
    'Enable', 'on', ...
    'BackgroundColor', 'w', ...
    'Position', ctrlPos.moduleEdit);

Children.moduleSelectButton = uicontrol( ...
    'Parent',            Children.codeFileOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.moduleSelectButton);

Children.moduleMenuButton = uicontrol( ...
    'Parent',            Children.codeFileOptGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.moduleMenuButton);

moduleCMenu = uicontextmenu('Parent', dlgfig);
set(Children.moduleEdit, 'UIContextMenu', moduleCMenu);
set(Children.moduleMenuButton, 'UIContextMenu', moduleCMenu);
menu.select = uimenu(moduleCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''moduleSelectButton'')',pageName));
menu.show = uimenu(moduleCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''moduleShowDDObject'')',pageName), ...
    'Separator','on');
set(moduleCMenu, 'UserData', menu);

Children.linkExtCodeCheckbox  = uicontrol( ...
    'Parent',             Children.codeFileOptGroupbox, ...
    'Style',              'checkbox', ...
    'String',             'Link external code', ...
    'Position',           ctrlPos.linkExtCodeCheckbox );

dlgdata.pageData{pageNum}.children = Children;
% end of function FcnCreateOptionsPage


%-------------------------------------------------------------------------------
% FcnManageOptionsPage manages control actions of options page
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-------------------------------------------------------------------------------
function [dlgdata,bModified] = FcnManageOptionsPage(pageNum, dlgfig, dlgdata, pageAction) %#ok<INUSL>

% prepare needed data
bModified = false;
Children  = dlgdata.pageData{pageNum}.children;
data      = dlgdata.data;

% branch depending on action
switch pageAction
    case 'fcnDescEdit'
        data.description = get(Children.fcnDescEdit,'String');
        bModified = true;
        
    case {'stepFcnClassMenuButton' 'restartFcnClassMenuButton' 'initFcnClassMenuButton' 'termFcnClassMenuButton'},
        panelPos = get(Children.codeOptGroupbox, 'Position');
        FcnSetMenuPosition(Children.(pageAction), panelPos(1:2));
        bModified = 1;
        
    case {'stepFcnClassSelectButton', 'stepFcnClassEdit'}
        [data.stepfunctionclass, bModified] = FcnGetFcnClass(pageAction(13:end),...
            data.stepfunctionclass, Children.stepFcnClassEdit);
    case {'restartFcnClassSelectButton', 'restartFcnClassEdit'}
        [data.restartfunctionclass, bModified] = FcnGetFcnClass(pageAction(16:end),...
            data.restartfunctionclass, Children.restartFcnClassEdit);
    case {'initFcnClassSelectButton', 'initFcnClassEdit'}
        [data.initfunctionclass, bModified] = FcnGetFcnClass(pageAction(13:end),...
            data.initfunctionclass, Children.initFcnClassEdit);
    case {'termFcnClassSelectButton', 'termFcnClassEdit'}
        [data.termfunctionclass, bModified] = FcnGetFcnClass(pageAction(13:end),...
            data.termfunctionclass, Children.termFcnClassEdit);
    case {'termFcnEditDDObject', 'initFcnEditDDObject', 'restartFcnEditDDObject', ...
            'stepFcnEditDDObject'}
        % at the moment no dd function class dialog exists. This case should never happen.
    case {'termFcnShowDDObject', 'initFcnShowDDObject', 'restartFcnShowDDObject', ...
            'stepFcnShowDDObject'}
        switch pageAction
            case 'termFcnShowDDObject'
                selectedFcnClass = data.termfunctionclass;
            case 'initFcnShowDDObject'
                selectedFcnClass = data.initfunctionclass;
            case 'restartFcnShowDDObject'
                selectedFcnClass = data.restartfunctionclass;
            case 'stepFcnShowDDObject'
                selectedFcnClass = data.stepfunctionclass;
        end
        if strcmp(selectedFcnClass, 'default') || isempty(selectedFcnClass)
            % jump to node in DD Manager
            dsddman('Select', '/Pool/FunctionClasses');
        else
            % jump to function object in DD Manager
            varPath = ['/Pool/FunctionClasses/' selectedFcnClass];
            dsddman('Select', varPath);
        end
    case {'initFcnNameForce', 'termFcnNameForce', 'restartFcnNameForce'}
        switch pageAction
            case 'initFcnNameForce'
                data.forceinitfunction = get(Children.initFcnNameForce,'Value');
            case 'termFcnNameForce'
                data.forcetermfunction = get(Children.termFcnNameForce,'Value');
            case 'restartFcnNameForce'
                data.forcerestartfunction = get(Children.restartFcnNameForce,'Value');
        end; %switch
        bModified = true;
    case {'stepFcnNameEdit','restartFcnNameEdit', 'initFcnNameEdit', 'termFcnNameEdit'}
        switch pageAction
            case 'stepFcnNameEdit'
                data.stepfunctionname = FcnGetFcnName(Children.stepFcnNameEdit, ...
                    data.stepfunctionname, 'stepfunctionname');
            case 'restartFcnNameEdit'
                data.restartfunctionname = FcnGetFcnName(Children.restartFcnNameEdit, ...
                    data.restartfunctionname, 'restartfunctionname');
            case 'initFcnNameEdit'
                data.initfunctionname = FcnGetFcnName(Children.initFcnNameEdit, ...
                    data.initfunctionname, 'initfunctionname');
            case 'termFcnNameEdit'
                data.termfunctionname = FcnGetFcnName(Children.termFcnNameEdit, ...
                    data.termfunctionname, 'termfunctionname');
        end; %switch
        bModified = true;
    case 'subsystemIDEdit'
        subsystemID = tl_deblank(get(Children.subsystemIDEdit,'String'),2);
        % Check if subsystem ID is a valid string. If not, get alternative subsystem
        % ID (replace invalid characters by '_', no more than 10 characters).
        [ok, subsystemID] = FcnCheckSubsystemID(subsystemID);
        data.subsystemid = subsystemID;
        bModified = true;
    case 'cFileEdit'
        codefile = tl_deblank(get(Children.cFileEdit,'String'),2);
        % no detailed check if file name is ok. With TL 2.1 it was possible to use $S or
        % similar, therefore it is still possible
        [tmp,codefile,e]  = fileparts(codefile);
        while ~isempty(e),
            [tmp,codefile,e]  = fileparts(codefile);
        end
        data.codefile = codefile;
        bModified = true;
        
    case 'moduleMenuButton'
        panelPos = get(Children.codeFileOptGroupbox, 'Position');
        FcnSetMenuPosition(Children.(pageAction), panelPos(1:2));
        bModified = 1;
        
    case 'moduleSelectButton'
        % SelectButton button: Get new FileSpecification from reference selection dialog
        data.module = dsdd( 'SelectObject', ...
            'entryPath',       '/Pool/Modules', ...
            'CurrentPath',     data.module, ...
            'ObjectKind',      'Module');
        bModified = true;
    case 'moduleEdit'
        % Edit field: Get new module from edit field
        data.module = tl_deblank(get(Children.moduleEdit,'String'),2);
        bModified = true;
    case 'moduleShowDDObject'
        if dsdd('exist', ['/Pool/Modules/' data.module]);
            % jump to function object in DD Manager
            modulePath = ['/Pool/Modules/' data.module];
            dsddman('Select', modulePath);
        else
            % jump to node in DD Manager
            dsddman('Select', '/Pool/Modules');
        end
    case 'reuseFcnCheckbox'
        data.forcereuse = get(Children.reuseFcnCheckbox,'Value');
        bModified = true;
    case 'linkExtCodeCheckbox'
        data.linkfile = get(Children.linkExtCodeCheckbox,'Value');
        bModified = true;
    otherwise
        error(['Invalid action ''' pageAction'''']);
end; %switch

dlgdata.data = data;
% end of function FcnManageOptionsPage


%-------------------------------------------------------------------------------
% FcnSetMenuPosition calculates position of contextmenu
%
% INPUT ARGUMENTS
%   ctrlHandle  handle of control
%   panelStart  cx position of panel
%
% OUTPUT ARGUMENTS
%   - / -
%-------------------------------------------------------------------------------
function FcnSetMenuPosition(ctrlHandle, panelStart)

pos = get(ctrlHandle, 'Position') + [panelStart 0 0];
cmenu = get(ctrlHandle, 'UIContextmenu');
commonGeom = ds_get_common_geometry;
textExtent = commonGeom.textExtent;
labelStrings = get(get(cmenu, 'Children'), 'Label');
maxext = 0;
for k = 1 : numel(labelStrings)
    set(textExtent, 'String', labelStrings{k});
    ext = get(textExtent, 'Extent');
    maxext = max(maxext, ext(3));
end
position = [pos(1)-32-maxext, pos(2)];
set(cmenu, 'Position', position, 'Visible', 'on');


%-------------------------------------------------------------------------------
% FcnUpdateOptionsPage updates the controls of the options tab
%
% INPUT ARGUMENTS
%   dlgfig      figure handle of dialog
%   dlgdata     dialog data
%   pageNum     page Number
%
% OUTPUT ARGUMENTS
%   - / -
%-------------------------------------------------------------------------------
function FcnUpdateOptionsPage(dlgfig,dlgdata,pageNum)

% early return if children are missing
Children = dlgdata.pageData{pageNum}.children;
if isempty(Children),
    return
end; %if

if dlgdata.extdata.bIsEditMode
    msg = ['   The dual edit mode is active ' char(10) '    to visualize both standard as well as AUTOSAR code generation settings. '];
    set(dlgdata.pageData{pageNum}.children.dualEditText, ...
        'String', msg, ...
        'Enable', 'on', ...
        'ForegroundColor',    'w', ...
        'BackgroundColor',    [.9 .5 0] ...    % orange
        );
else
    set(dlgdata.pageData{pageNum}.children.dualEditText, ...
        'String', ' ', ...
        'ForegroundColor',    'b', ...
        'BackgroundColor',    get(0,'DefaultUicontrolBackgroundColor') ...
        );
end

data = dlgdata.data;

bIsAutosar = dlgdata.data.autosar.isrunnable || dlgdata.data.autosar.isoperationcall;
if bIsAutosar && any(dlgdata.extdata.codegenmode == [0 2]) && ~dlgdata.extdata.bIsEditMode
    % AUTOSAR mode is activated, disable all output controls
    ctrlNames = fieldnames(Children);
    ctrlNames = ctrlNames(cellfun('isempty', regexp(ctrlNames, 'Autosar', 'match')));
    for k = 1:numel(ctrlNames)
        eval(['hChild = Children.', ctrlNames{k}, ';']);
        % There are some control names which are associated to more than
        % one handle. Thus use following loop.
        for m = 1:numel(hChild)
            tmpUserData = get(hChild(m), 'UserData');
            tmpUserData.ctrlStatus.enable = 'off';
            set(hChild(m), 'UserData', tmpUserData);
        end
    end
    TLSetCtrlsStatus(dlgfig, Children, ctrlNames);
else
    % invoke standard update function
    if dlgdata.bIsFullVs
        enableOn = 'on';
        enableEdit = 'on';
    else
        enableOn = 'off';
        enableEdit = 'inactive';
    end
    
    % default control status for controls
    fcnDescEditCtrlStatus                 = struct('enable', 'on', 'string', '');
    stepFcnClassEditCtrlStatus            = struct('enable', enableEdit, 'string', '');
    stepFcnClassSelectButtonCtrlStatus    = struct('enable', enableOn); %#ok<NASGU>
    stepFcnClassMenuButtonCtrlStatus      = struct('enable', enableOn); %#ok<NASGU>
    stepFcnNameEditCtrlStatus             = struct('enable', enableEdit, 'string', '');
    restartFcnClassEditCtrlStatus         = struct('enable', enableEdit, 'string', '');
    restartFcnClassSelectButtonCtrlStatus = struct('enable', enableOn);
    restartFcnClassMenuButtonCtrlStatus   = struct('enable', enableOn);
    restartFcnNameEditCtrlStatus          = struct('enable', enableEdit, 'string', '');
    restartFcnNameForceCtrlStatus         = struct('enable', enableOn, 'value', 0);
    initFcnClassEditCtrlStatus            = struct('enable', enableEdit, 'string', '');
    initFcnClassSelectButtonCtrlStatus    = struct('enable', enableOn); %#ok<NASGU>
    initFcnClassMenuButtonCtrlStatus      = struct('enable', enableOn); %#ok<NASGU>
    initFcnNameEditCtrlStatus             = struct('enable', enableEdit, 'string', '');
    initFcnNameForceCtrlStatus            = struct('enable', enableOn, 'value', 0);
    termFcnClassEditCtrlStatus            = struct('enable', enableEdit, 'string', '');
    termFcnClassSelectButtonCtrlStatus    = struct('enable', enableOn);
    termFcnClassMenuButtonCtrlStatus      = struct('enable', enableOn);
    termFcnNameEditCtrlStatus             = struct('enable', enableEdit, 'string', '');
    termFcnNameForceCtrlStatus            = struct('enable', enableOn, 'value', 0);
    subsystemIDEditCtrlStatus             = struct('enable', enableEdit, 'string', '');
    reuseFcnCheckboxCtrlStatus            = struct('enable', enableOn, 'value', 0);
    cFileEditCtrlStatus                   = struct('enable', enableEdit, 'string', '');
    moduleEditCtrlStatus                  = struct('enable', enableEdit, 'string', '');
    moduleSelectButtonCtrlStatus = struct('enable', enableOn);
    moduleMenuButtonCtrlStatus  = struct('enable', enableOn);
    linkExtCodeCheckboxCtrlStatus   = struct('enable', enableOn, 'value', 0);
    
    % check if function is function-call triggered. It is not checked if the function call is
    % triggered from outside the TL root system
    hParent = get_param(dlgdata.model,'Parent');
    bFcnCallTrigg = ~isempty(find_system(hParent, ...
        'SearchDepth',       1, ...
        'LookUnderMasks',    'all', ...
        'FollowLinks',       'on', ...
        'BlockType',         'TriggerPort', ...
        'TriggerType',       'function-call'));
    
    % If one of the following is true, all fields on the options page are enabled:
    % 1) the function block is located on the root level of a TargetLink subsystem ...
    bRootLevel = any(strcmp(get_param(hParent,'Tag'),{'MIL Subsystem' 'disabled MIL Subsystem'}));
    % 2) or the stepfunction is a user-defined extern function class or is (possibly) called from extern,
    %    i.e. (bStepFcnExtern) or (bFcnCallTrigg) is true
    % 3) or incremental code generation is activated.
    bIncCode = dlgdata.data.incrcodegen;
    bRootOrInc = bRootLevel || bIncCode;
    
    % enable/disable all controls
    % So are the functionclasses really invalid?
    % 1) check if functionclasses exist in the current DD
    %    (since they could have been changed by the user via API)
    stepFunctionClass    = dlgdata.data.stepfunctionclass;
    restartFunctionClass = dlgdata.data.restartfunctionclass;
    initFunctionClass    = dlgdata.data.initfunctionclass;
    termFunctionClass    = dlgdata.data.termfunctionclass;
    
    [bStepClassValid, hStepFunctionclass]       = FcnExistFcnClass(stepFunctionClass);
    [bRestartClassValid, hRestartFunctionclass] = FcnExistFcnClass(restartFunctionClass);
    [bInitClassValid, hInitFunctionclass]       = FcnExistFcnClass(initFunctionClass);
    [bTermClassValid]                           = FcnExistFcnClass(termFunctionClass);
    
    % 2) check if the functionclasses are inconsistent with other
    %    properties of the block (in FcnIsFcnClassConsistent())
    if bStepClassValid
        stepFcnClassEditCtrlStatus.iserror = ~FcnIsFcnClassConsistent('step', stepFunctionClass, bFcnCallTrigg, bRootOrInc);
        % get storage of class (needed later)
        bStepFcnExtern = strcmp(dsdd('GetStorage', hStepFunctionclass),'extern');
        % stepFcnFileName = dsdd('GetModule', hStepFunctionclass);
        stepFcnFileName  = '';
        modulePath = '';
        hStepFcnFileName = dsdd('GetModuleRefTarget', hStepFunctionclass);
        if ~isempty(hStepFcnFileName)
            stepFcnFileName = dsdd('GetAttribute', hStepFcnFileName, 'name');
            modulePath = dsdd('GetAttribute', hStepFcnFileName, 'path');
            idx = strfind(modulePath, '/Modules/');
            if ~isempty(idx)
                modulePath = modulePath(idx+9:end);
            end
        end
    else
        % make sure the if-clause below is never entered
        bStepFcnExtern = false;
        stepFcnFileName = '';
        modulePath = '';
    end; %if
    if bRestartClassValid
        % restartfunctionclass exist in DD ...
        bRestartFcnExtern = strcmp(dsdd('GetStorage', hRestartFunctionclass),'extern');
        bRestartFcnDefault = strcmp(restartFunctionClass,'default');
        % but is there a inconsistency with other block data?
        restartFcnClassEditCtrlStatus.iserror = ~FcnIsFcnClassConsistent('restart', restartFunctionClass,bFcnCallTrigg, bRootOrInc);
    else
        bRestartFcnExtern = true;
        bRestartFcnDefault = true;
    end; %if
    if bInitClassValid
        % initfunctionclass exist in DD ...
        bInitFcnExtern = strcmp(dsdd('GetStorage', hInitFunctionclass),'extern');
        bInitFcnDefault = strcmp(initFunctionClass,'default');
        % but is there a inconsistency with other block data?
        initFcnClassEditCtrlStatus.iserror = ~FcnIsFcnClassConsistent('init', initFunctionClass,bFcnCallTrigg, bRootOrInc);
    else
        bInitFcnExtern = true;
        bInitFcnDefault = true;
    end; %if
    if bTermClassValid
        % termfunctionclass exist in DD...
        termFcnClassEditCtrlStatus.iserror = ~FcnIsFcnClassConsistent('term', termFunctionClass,bFcnCallTrigg, bRootOrInc);
    end; %if
    
    % 3) check if the functionclasses are inconsistent with each other...
    if (bStepFcnExtern && ~(bInitFcnDefault || bInitFcnExtern))
        ds_error_msg({ ...
            'The current step function class', ...
            ['  ' stepFunctionClass], ...
            'has the ''extern'' attribute, while the current initialization function class', ...
            ['  ' initFunctionClass], ...
            'is neither extern, nor ''default'' .'}, ...
            'MessageNumber',1222,'Title','Function classes incompliant');
        stepFcnClassEditCtrlStatus.iserror = true;
        initFcnClassEditCtrlStatus.iserror = true;
    end; %if
    if (bStepFcnExtern && ~(bRestartFcnDefault || bRestartFcnExtern))
        ds_error_msg({ ...
            'The current step function class', ...
            ['  ' stepFunctionClass], ...
            'has the ''extern'' attribute, while the current restart function class', ...
            ['  ' restartFunctionClass], ...
            'is neither extern, nor ''default'' .'}, ...
            'MessageNumber',1222,'Title','Function classes incompliant');
        stepFcnClassEditCtrlStatus.iserror = true;
        restartFcnClassEditCtrlStatus.iserror = true;
    end; %if
    
    % If one of the above is true, all fields on the options page are enabled
    bEnableAll = bStepFcnExtern || bFcnCallTrigg || bIncCode || bRootLevel;
    if bEnableAll
        enableAll = enableOn;
        enableAllEdit = enableEdit;
    else
        enableAll = 'off';
        enableAllEdit = 'off';
    end
    
    % if valid module is selected, codefile field must be gray
    if ~isempty(modulePath) && ~bStepFcnExtern
        module = modulePath;
    else
        module = data.module;
    end
    bValidModule = dsdd('exist', ['/Pool/Modules/' module]);
    % The 'codefile' edit field is active if the stepfunction is either extern or
    % name is not defined via function class attribute 'module'
    bModuleEnabled = bStepFcnExtern || isempty(stepFcnFileName);
    if ~isempty(stepFcnFileName) && ~bStepFcnExtern
        codefile = stepFcnFileName;
    else
        codefile = data.codefile;
    end
    if bModuleEnabled
        if isempty(module)
            moduleEnable = 'off';
            codefileEnable = 'on';
        else
            moduleEnable = 'on';
            if bValidModule
                codefileEnable = 'inactive';
                idxModule = strfind(data.module, '/');
                if ~isempty(idxModule)
                    % do not save standard interface path
                    codefile = module(idxModule(end)+1:end);
                end
            else
                moduleEditCtrlStatus.iserror = true;
                codefileEnable = 'off';
            end
        end
    else
        codefileEnable = 'inactive';
        moduleEnable = 'inactive';
    end
    
    % Set the color of the Subsystem ID: red if not valid, black otherwise
    [ok, data.subsystemid] =  FcnCheckSubsystemID(data.subsystemid);
    subsystemIDEditCtrlStatus.iserror = ~ok;
    
    % If input of edit field is 'default', it has to be changed to 'default '
    % to make it possible to display it
    [stepFunctionClass, bStepFcnIsDef]       = FcnChangeDefaultInput(stepFunctionClass);
    [restartFunctionClass, bRestartFcnIsDef] = FcnChangeDefaultInput(restartFunctionClass);
    [initFunctionClass, bInitFcnIsDef]       = FcnChangeDefaultInput(initFunctionClass);
    [termFunctionClass, bTermFcnIsDef]       = FcnChangeDefaultInput(termFunctionClass);
    stepFunctionName    = FcnChangeDefaultInput(data.stepfunctionname);
    restartFunctionName = FcnChangeDefaultInput(data.restartfunctionname);
    initFunctionName    = FcnChangeDefaultInput(data.initfunctionname);
    termFunctionName    = FcnChangeDefaultInput(data.termfunctionname);
    subsystemID         = FcnChangeDefaultInput(data.subsystemid);
    description         = FcnChangeDefaultInput(data.description);
    
    % make string single-line, because edit control can not have multi-line text
    descString  = strrep(description, char(10),' ');
    fcnDescEditCtrlStatus.string = descString;
    stepFcnClassEditCtrlStatus.string = stepFunctionClass;
    stepFcnNameEditCtrlStatus.string = stepFunctionName;
    initFcnClassEditCtrlStatus.string = initFunctionClass;
    initFcnNameEditCtrlStatus.string = initFunctionName;
    subsystemIDEditCtrlStatus.string = subsystemID;
    reuseFcnCheckboxCtrlStatus.value = data.forcereuse;
    
    % Set all fields where the Enable state depends on other properties of the block
    % function class, name, force
    restartFcnNameEditCtrlStatus.string = restartFunctionName;
    restartFcnNameEditCtrlStatus.enable = enableAll;
    restartFcnNameForceCtrlStatus.value = data.forcerestartfunction;
    restartFcnNameForceCtrlStatus.enable = enableAll;
    restartFcnClassEditCtrlStatus.string = restartFunctionClass;
    restartFcnClassEditCtrlStatus.enable = enableAll;
    restartFcnClassSelectButtonCtrlStatus.enable = enableAll;
    restartFcnClassMenuButtonCtrlStatus.enable = enableAll;
    initFcnNameForceCtrlStatus.value = data.forceinitfunction;
    initFcnNameForceCtrlStatus.enable = enableAll;
    termFcnNameEditCtrlStatus.string = termFunctionName;
    termFcnNameEditCtrlStatus.enable = enableAllEdit;
    termFcnNameForceCtrlStatus.value = data.forcetermfunction;
    termFcnNameForceCtrlStatus.enable = enableAll;
    termFcnClassEditCtrlStatus.string = termFunctionClass;
    termFcnClassEditCtrlStatus.enable = enableAllEdit;
    termFcnClassSelectButtonCtrlStatus.enable = enableAll;
    termFcnClassMenuButtonCtrlStatus.enable = enableAll;
    
    % "show" is disabled, if function class is invalid or empty
    bMissingTermDDFcn = ~isempty(termFunctionClass) ...
        && ~(dsdd('Exist',termFunctionClass , ...
        'Parent',       '/Pool/FunctionClasses', ...
        'ObjectKind',   'FunctionClass'));
    bMissingRestartDDFcn = ~isempty(restartFunctionClass) ...
        && ~(dsdd('Exist',restartFunctionClass , ...
        'Parent',       '/Pool/FunctionClasses', ...
        'ObjectKind',   'FunctionClass'));
    bMissingInitDDFcn = ~isempty(initFunctionClass) ...
        && ~(dsdd('Exist',initFunctionClass , ...
        'Parent',       '/Pool/FunctionClasses', ...
        'ObjectKind',   'FunctionClass'));
    bMissingStepDDFcn = ~isempty(stepFunctionClass) ...
        && ~(dsdd('Exist',stepFunctionClass , ...
        'Parent',       '/Pool/FunctionClasses', ...
        'ObjectKind',   'FunctionClass'));
    
    % set status of context menu controls
    stepClassCMenu    = get(Children.stepFcnClassEdit, 'UIContextMenu');
    stepClassMenu     = get(stepClassCMenu, 'UserData');
    menuSelectStatus = struct('enable', flag2str(dlgdata.bIsFullVs));
    UserData = get(stepClassMenu.select, 'UserData');
    UserData.ctrlStatus = menuSelectStatus;
    set(stepClassMenu.select, 'UserData', UserData);
    menuEditStatus = struct('enable', 'off');
    UserData = get(stepClassMenu.edit, 'UserData');
    UserData.ctrlStatus = menuEditStatus;
    set(stepClassMenu.edit, 'UserData', UserData);
    menuShowStatus = struct('enable', flag2str(dlgdata.bIsFullVs && (~bMissingStepDDFcn || bStepFcnIsDef)));
    UserData = get(stepClassMenu.show, 'UserData');
    UserData.ctrlStatus = menuShowStatus;
    set(stepClassMenu.show, 'UserData', UserData);
    
    restartClassCMenu    = get(Children.restartFcnClassEdit, 'UIContextMenu');
    restartClassMenu     = get(restartClassCMenu, 'UserData');
    menuSelectStatus = struct('enable', enableAll);
    UserData = get(restartClassMenu.select, 'UserData');
    UserData.ctrlStatus = menuSelectStatus;
    set(restartClassMenu.select, 'UserData', UserData);
    menuEditStatus = struct('enable', 'off');
    UserData = get(restartClassMenu.edit, 'UserData');
    UserData.ctrlStatus = menuEditStatus;
    set(restartClassMenu.edit, 'UserData', UserData);
    menuShowStatus = struct('enable', flag2str(bEnableAll && (~bMissingRestartDDFcn || bRestartFcnIsDef)));
    UserData = get(restartClassMenu.show, 'UserData');
    UserData.ctrlStatus = menuShowStatus;
    set(restartClassMenu.show, 'UserData', UserData);
    
    initClassCMenu    = get(Children.initFcnClassEdit, 'UIContextMenu');
    initClassMenu     = get(initClassCMenu, 'UserData');
    menuSelectStatus = struct('enable', flag2str(dlgdata.bIsFullVs));
    UserData = get(initClassMenu.select, 'UserData');
    UserData.ctrlStatus = menuSelectStatus;
    set(initClassMenu.select, 'UserData', UserData);
    menuEditStatus = struct('enable', 'off');
    UserData = get(initClassMenu.edit, 'UserData');
    UserData.ctrlStatus = menuEditStatus;
    set(initClassMenu.edit, 'UserData', UserData);
    menuShowStatus = struct('enable', flag2str(dlgdata.bIsFullVs && (~bMissingInitDDFcn || bInitFcnIsDef)));
    UserData = get(initClassMenu.show, 'UserData');
    UserData.ctrlStatus = menuShowStatus;
    set(initClassMenu.show, 'UserData', UserData);
    
    termClassCMenu    = get(Children.termFcnClassEdit, 'UIContextMenu');
    termClassMenu     = get(termClassCMenu, 'UserData');
    menuSelectStatus = struct('enable', enableAll);
    UserData = get(termClassMenu.select, 'UserData');
    UserData.ctrlStatus = menuSelectStatus;
    set(termClassMenu.select, 'UserData', UserData);
    menuEditStatus = struct('enable', 'off');
    UserData = get(termClassMenu.edit, 'UserData');
    UserData.ctrlStatus = menuEditStatus;
    set(termClassMenu.edit, 'UserData', UserData);
    menuShowStatus = struct('enable', flag2str(bEnableAll && (~bMissingTermDDFcn || bTermFcnIsDef)));
    UserData = get(termClassMenu.show, 'UserData');
    UserData.ctrlStatus = menuShowStatus;
    set(termClassMenu.show, 'UserData', UserData);
    
    % codefile and module
    cFileEditCtrlStatus.string = codefile;
    cFileEditCtrlStatus.enable = codefileEnable;
    moduleEditCtrlStatus.string = module;
    moduleEditCtrlStatus.enable = moduleEnable;
    moduleSelectButtonCtrlStatus.enable = flag2str(bModuleEnabled);
    moduleMenuButtonCtrlStatus.enable = flag2str(bModuleEnabled);
    
    % set status of context menu controls:
    moduleCMenu    = get(Children.moduleEdit, 'UIContextMenu');
    moduleMenu     = get(moduleCMenu, 'UserData');
    menuSelectStatus = struct('enable', flag2str(bModuleEnabled));
    UserData = get(moduleMenu.select, 'UserData');
    UserData.ctrlStatus = menuSelectStatus;
    set(moduleMenu.select, 'UserData', UserData);
    menuShowStatus = struct('enable', flag2str(dlgdata.bIsFullVs && ~isempty(module)));
    UserData = get(moduleMenu.show, 'UserData');
    UserData.ctrlStatus = menuShowStatus;
    set(moduleMenu.show, 'UserData', UserData);
    
    % The 'Link external code' checkbox is only active if the stepfunction is a
    % user-defined extern function class
    linkExtCodeCheckboxCtrlStatus.value = data.linkfile;
    linkExtCodeCheckboxCtrlStatus.enable = flag2str(bStepFcnExtern);
    
    % write back control status of extra controls to the controls' UserData property
    ctrlsList = fieldnames(Children);
    ctrlsList(strcmp(ctrlsList,'dualEditText')) = [];
    ctrlsList = ctrlsList(cellfun('isempty', regexp(ctrlsList, 'Label', 'match')));
    ctrlsList = ctrlsList(cellfun('isempty', regexp(ctrlsList, 'Groupbox', 'match')));
    for ctrlsNo=1:length(ctrlsList)
        ctrl = Children.(ctrlsList{ctrlsNo});
        UserData = get(ctrl, 'UserData');
        UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
        set(ctrl, 'UserData', UserData);
    end
    TLSetCtrlsStatus(dlgfig, Children, ctrlsList);
end
% end of function FcnUpdateOptionsPage


%-------------------------------------------------------------------------------
% FcnGetFcnClass handles the function class edit field and browse buttons.
%
% INPUT ARGUMENTS
%   action      either 'Edit' or 'Browse'
%   fcnclass    old functionclass
%   editfield   field user edited
%
% OUTPUT ARGUMENTS
%   fcnclass    new functionclass:
%               - new class if it is valid or if the new AND old class are invalid
%               - old class if the new class is not valid but the old class is
%   update      indicates if the dialog has to be updated (Update not neccessary if
%               invalid class is replaced by invalid class)
%-------------------------------------------------------------------------------
function [fcnclass, update] = FcnGetFcnClass(action, fcnclass, editfield)

update = true;
switch action
    case 'SelectButton'
        % Select button: Get new class from reference selection dialog
        newclass = dsdd( 'SelectObject', ...
            'CurrentPath', fcnclass, ...
            'ObjectKind',  'FunctionClass');
        if ~isempty(newclass),
            bClassValid = FcnExistFcnClass(newclass);
        else
            bClassValid = false;
        end; %if
    case 'Edit'
        % Edit field: Get new class from edit field
        newclass = tl_deblank(get(editfield,'String'),2);
        bClassValid = FcnExistFcnClass(newclass);
    otherwise
        error(['Invalid action ''' action '''']);
end; %switch

if bClassValid
    %if new class is valid, return new class
    fcnclass = newclass;
elseif ~(dsdd('exist',fcnclass,'Parent','Pool/FunctionClasses') ...
        || strcmp(fcnclass,'default'))
    % neither new, nor old class is valid
    fcnclass = newclass;
    % Do not call update function if class has been changed from an invalid
    % name to an invalid name. Call of update function would trigger error message twice!
    update = false;
end; %if
% end of function FcnGetFcnClass


%-------------------------------------------------------------------------------
% FcnGetFcnName handles the function name edit field.
%
% INPUT ARGUMENTS
%   Edit        edit field which has been modified
%
% OUTPUT ARGUMENTS
%   fcnname     new functionname:
%               - new class if it is valid
%               - old name if the new name is not valid
%-------------------------------------------------------------------------------
function [fcnname] = FcnGetFcnName(editCtrl,oldfcnname,field)

newname = tl_deblank(get(editCtrl,'String'),2);

dataDesc = tl_manage_blockset('GetDataDescription', 'TL_Function');
idxVar = strcmp(field, dataDesc(:,1));
% extract block variable description
[tmpName, ok] = tl_isvarname(newname,dataDesc{idxVar, 2}{1,5});

if ok
    % fcnname is valid name: take fcnname
    fcnname = newname;
else
    % fcnname is invalid name: take old fcnname
    ds_error_msg({ ...
        ['New value ''' newname ''' is not a valid function name!.']}, ...
        'Title','Invalid TargetLink function name');
    fcnname = oldfcnname;
end


%-------------------------------------------------------------------------------
% FcnExistFcnClass checks if functionclass exist in the current Data Dictionary.
%
% INPUT ARGUMENTS
%   functionclass   function class
%
% OUTPUT ARGUMENTS
%   bClassValid     1 if class exists in DD, zero otherwise
%   hFcnClass       handle in DD
%-------------------------------------------------------------------------------
function [bClassValid, hFcnClass] = FcnExistFcnClass(fcnclass)

% check if functionclass is a valid functionclass
[bClassValid,hFcnClass] = dsdd('exist',fcnclass,'Parent','Pool/FunctionClasses');
if strcmp(fcnclass,'default')
    % default class must not further be checked
    bClassValid = 1;
    return
elseif ~bClassValid,
    % function class does not exist in data dictionary
    ds_error_msg({ ...
        % ['There is no ''' functionclass ''' function class in the current Data Dictionary file.'], ...
        % 'Enter ''default'' or select an existing function class.'}, ...
        % 'MessageNumber',1219,'Title','Invalid function class');
        'The current function class identifier', ...
        ['   ' fcnclass], ...
        'is undefined. Supplement the function class section of', ...
        'your Data Dictionary file or select a defined function class.'}, ...
        'MessageNumber',1219,'Title','Invalid function class');
else
    objKind = dsdd('getAttribute',hFcnClass,'ObjectKind');
    if ~strcmpi(objKind ,'FunctionClass'),
        ds_error_msg({ ...
            'The current identifier', ...
            ['   ',fcnclass], ...
            ['does not denote a function class, but a ' objKind   ' object.']}, ...
            'MessageNumber',1218,'Title','Not a function class');
        bClassValid = 0;
    end; %if
end; %if
% end of function FcnExistFcnClass


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   [color] =  FcnIsFcnClassConsistent(functiontype, functionclass,bFcnCallTrigg, bRootOrInc)
%   Function to check if the given functionclass is consistent with other
%   properties of the block. The consistency with other functionclasses on
%   the options page is not done here, but later in the Update Function. In
%   case of inconsistency, an error is displayed and the function names are
%   displayed in red.
%   Function is called by FcnUpdateOptionsPage()
%
% INPUT ARGUMENTS
%   functiontype     'step', 'restart', 'term' or 'init'
%   functionclass    Function class
%   bFcnCallTrigg    true, if function is called from extern, false otherwise
%   bRootOrInc       true, if subsystem is root or incremental code gen is activated
%
% OUTPUT ARGUMENTS
%   success         true, if function class is allowed, false otherwise
%-------------------------------------------------------------------------------
function success =  FcnIsFcnClassConsistent(functiontype, functionclass,bFcnCallTrigg, bRootOrInc)

% default return value
success = true;
% We already know that the functionclass is a valid class, since otherwise
% this function would not have been called by FcnUpdateOptionsPage()
if strcmp(functionclass, 'default')
    bCompilerInline = 0;
    bISR = 0;
else
    hFunctionclass = dsdd('GetAttribute',functionclass,'hDDObject', ...
        'Parent','Pool/FunctionClasses');
    bCompilerInline = dsdd('GetCompilerInline', hFunctionclass);
    bISR            = dsdd('GetInterrupt',      hFunctionclass);
end; %if

% error message if function class has inline attribute but is not root step function or
% a step function for which incremental code generation is activated
if bCompilerInline && ( ~strcmp(functiontype, 'step') || bRootOrInc)
    ds_error_msg({ ...
        'The current function class', ...
        ['   ' functionclass], ...
        'has the ''inline'' attribute which', ...
        'is only permitted for non-root step functions.'}, ...
        'MessageNumber',1221,'Title','Incompliant function class');
    success = false;
end; %if

% error message if function class has interrupt attribute but is not non-root step function
if bISR && ( ~strcmp(functiontype, 'step') || ~(bRootOrInc || bFcnCallTrigg)),
    ds_error_msg({ ...
        'The current function class', ...
        ['  ' functionclass], ...
        'has the ''interrupt'' attribute, which is only possible' ...
        'for externally called step functions.'}, ...
        'MessageNumber',1220,'Title','Incompliant function class');
    success = false;
end; %if
% end of function FcnIsFcnClassConsistent


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   [ok, subsystemID] =  FcnCheckSubsystemID(subsystemID)
%   Function to check if the given Subsystem ID is correct, i.e. the string
%   complies with regular expression and is not too long.
%   Function is called by FcnUpdateOptionsPage() and FcnManageOptionsPage()
%
% INPUT ARGUMENTS
%   subsystemID: subsystem ID
%
% OUTPUT ARGUMENTS
%   ok:          1 if functionname is ok, zero otherwise
%   subsystemID: new subsystem ID
%-------------------------------------------------------------------------------
function [ok, subsystemID] =  FcnCheckSubsystemID(subsystemID)
ok = 1;
invalidChar = regexp(subsystemID,'[^a-zA-Z0-9_]');
if (~isempty(subsystemID)) && ((~isempty(invalidChar)) || (length(subsystemID) > 10)),
    % ID is invalid if it is not empty and invalid characters are used or ID is too long
    ok = 0;
    ds_error_msg({ ...
        ['You cannot use ''' subsystemID ''' as TargetLink subsystem ID.'], ...
        'Use only letters (a .. z, A .. Z), digits (0 .. 9) and underscores (_).', ...
        'The TargetLink subsystem ID shouldn''t be longer than 10 characters.'}, ...
        'Title','Invalid TargetLink subsystem ID');
    % Replace invalid characters by '_', abbreviate subsystem ID (max 10 characters)
    subsystemID(invalidChar) = '_';
    subsystemID = subsystemID(1:min(end,10));
end; %if
% end of function FcnCheckSubsystemID


%===============================================================================
%
%                                Arguments Page
%
%===============================================================================

%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   [sheetDims,ctrlPos] = FcnArgumentsCtrlPosition(commonGeom,sheetDims)
%   function to calculate positions of blockspecific controls of arguments
%   page. Positions are calculated from the bottom left of the fig to avoid
%   dependencies on figure size.
%
% INPUT ARGUMENTS
%   commonGeom: common geometries like text height, ...
%   sheetDims:  total sheetDims
%
% OUTPUT ARGUMENTS
%   ctrlPos:    position of the controls
%   sheetDims:  total sheetDims of all controls ([width height])
%-------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnArgumentsCtrlPositions(commonGeom,sheetDims)

% get the sizes of the edit fields, checkboxes, buttons and labels (last is
% determined from the longest label)
strings_and_styles = {...
    repmat('m',1,40),            'edit'; ...
    'Scaling invariant',         'checkbox'; ...
    ' Update ',                  'pushbutton'; ...
    'Preferred order of function arguments:',   'text'; ...
    'Additional pointer arguments:',   'text'};
[scalingPropEditSize, ...
    scalInvCheckboxSize, ...
    updateModelPushButtonSize, ...
    fcnArgsOrderLabelSize, ...
    additionalArgsLabelSize] = ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% get page partitioning and row/column spacing
widths = scalingPropEditSize(1);
[tmp,tmp,colDelta,tmp] = ds_get_gui_columns(widths,commonGeom); %#ok

% adjust partitioning: two columns are needed.
scalingPropEditWidth = max(scalingPropEditSize(1), ...
    sheetDims(1) - 2 * commonGeom.sheetSideEdgeBuffer - 2 * commonGeom.frameSideEdgeBuffer);
argumentsEditWidth = scalingPropEditWidth - colDelta/3 - updateModelPushButtonSize(1);
widths = [argumentsEditWidth, updateModelPushButtonSize(1)];
[col,tmp,tmp,rowDelta] = ds_get_gui_columns(widths,commonGeom);

% all groupboxes on the page have the same width, which is the maximum of
% the 'needed' width and the width of the page
argGroupboxWidth = scalingPropEditWidth + 2 * commonGeom.frameSideEdgeBuffer;

% Edit height is the same for all edit fields on this tab
editHeight = 5 * commonGeom.editHeight;

% Position of scaling invariance groupbox
scalInvGroupboxHeight = commonGeom.frameTopEdgeBuffer ...
    + scalInvCheckboxSize(2) ...
    + fcnArgsOrderLabelSize(2) + rowDelta ...
    + editHeight ...
    + commonGeom.frameBottomEdgeBuffer;
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + commonGeom.sheetBottomEdgeBuffer;
ctrlPos.scalInvGroupbox =  [cx,cy,argGroupboxWidth,scalInvGroupboxHeight];

% Position of Scaling propagation controls: edit, label and checkbox
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.scalPropEdit = [cx, cy, scalingPropEditWidth, editHeight];
cx = col(1);
cy = cy + editHeight;
ctrlPos.scalPropLabel = [cx cy fcnArgsOrderLabelSize];
cy = cy + fcnArgsOrderLabelSize(2) + rowDelta;
ctrlPos.scalInvCheckbox = [cx cy scalInvCheckboxSize];

% Position of the function arguments groupbox
fcnArgGroupboxHeight = commonGeom.frameTopEdgeBuffer ...
    + 2 * fcnArgsOrderLabelSize(2) ...
    + 2 * (editHeight + rowDelta) ...
    + commonGeom.frameBottomEdgeBuffer;
cx = ctrlPos.scalInvGroupbox(1);
cy = ctrlPos.scalInvGroupbox(2) + scalInvGroupboxHeight...
    + commonGeom.textHeight;
ctrlPos.fcnArgGroupbox =  [cx,cy,argGroupboxWidth,fcnArgGroupboxHeight];

% Position of "additional pointer args" edit and "Select" pushbutton and label
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.additionalArgsEdit = [cx, cy, argumentsEditWidth, editHeight];
cx = col(2);
ctrlPos.addPushButton = [cx cy updateModelPushButtonSize];
cx = col(1);
cy = cy + editHeight;
ctrlPos.additionalArgsLabel = [cx cy additionalArgsLabelSize];

% Position of "Pref. order of function args" edit and "UpdateFromModel"
% pushbutton and label
cx = col(1);
cy = cy + commonGeom.textHeight + rowDelta;
ctrlPos.fcnArgsOrderEdit = [cx, cy, argumentsEditWidth, editHeight];
cx = col(2);
ctrlPos.updateModelPushButton = [cx cy updateModelPushButtonSize];
cx = col(1);
cy = cy + editHeight;
ctrlPos.fcnArgsOrderLabel = [cx cy fcnArgsOrderLabelSize];

% Width and height of page
width = argGroupboxWidth + 2 * commonGeom.sheetSideEdgeBuffer;
height = ctrlPos.fcnArgGroupbox(4) ...
    + ctrlPos.scalInvGroupbox(4) ...
    + 2*commonGeom.textHeight ...
    + commonGeom.sheetBottomEdgeBuffer;
sheetDims = [width height];
% end of function FcnArgumentsCtrlPositions


%-------------------------------------------------------------------------------
% FcnCreateArgumentsPage creates the arguments page.
%   Edit fields and checkboxes are left empty, they are filled out with the 
%   block data in the corresponding update function
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-------------------------------------------------------------------------------
function dlgdata = FcnCreateArgumentsPage(pageNum,dlgfig,dlgdata)

data = dlgdata.data;
ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;

% Scaling invariance groupbox
Children.scalInvGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Scaling invariance'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.scalInvGroupbox);

Children.scalPropEdit  = uicontrol( ...
    'Parent',             Children.scalInvGroupbox, ...
    'Min',                0, ...
    'Max',                2, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.scalPropEdit );

Children.scalPropLabel  = uicontrol( ...
    'Parent',             Children.scalInvGroupbox, ...
    'Style',              'text', ...
    'String',             'Scaling propagation:', ...
    'Position',           ctrlPos.scalPropLabel );

Children.scalInvCheckbox  = uicontrol( ...
    'Parent',             Children.scalInvGroupbox, ...
    'Value',              data.unscaledarguments, ...
    'Style',              'checkbox', ...
    'String',             'Scaling invariant', ...
    'Position',           ctrlPos.scalInvCheckbox );

% Function arguments groupbox
Children.fcnArgGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Function arguments'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.fcnArgGroupbox);

Children.updateModelPushButton = uicontrol( ...
    'Parent',            Children.fcnArgGroupbox, ...
    'Style',             'pushbutton', ...
    'String',            'Update', ...
    'Position',          ctrlPos.updateModelPushButton);

Children.fcnArgsOrderEdit  = uicontrol( ...
    'Parent',             Children.fcnArgGroupbox, ...
    'Min',                0, ...
    'Max',                2, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.fcnArgsOrderEdit );

Children.addPushButton = uicontrol( ...
    'Parent',            Children.fcnArgGroupbox, ...
    'Style',             'pushbutton', ...
    'String',            'Add ... ', ...
    'Position',          ctrlPos.addPushButton);

Children.additionalArgsEdit  = uicontrol( ...
    'Parent',             Children.fcnArgGroupbox, ...
    'Min',                0, ...
    'Max',                2, ...
    'Style',              'edit', ...
    'Position',           ctrlPos.additionalArgsEdit );

Children.fcnArgsOrderLabel = uicontrol( ...
    'Parent',             Children.fcnArgGroupbox, ...
    'Style',              'text', ...
    'String',             'Preferred order of function arguments:', ...
    'Position',           ctrlPos.fcnArgsOrderLabel);

Children.additionalArgsLabel = uicontrol( ...
    'Parent',             Children.fcnArgGroupbox, ...
    'Style',              'text', ...
    'String',             'Additional pointer arguments:', ...
    'Position',           ctrlPos.additionalArgsLabel);

dlgdata.pageData{pageNum}.children = Children;
% end of function FcnCreateArgumentsPage


%-------------------------------------------------------------------------------
% FcnManageArgumentsPage manages control actions on the arguments page of the dialog.
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   pageAction  action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-------------------------------------------------------------------------------
function [dlgdata,bModified] = FcnManageArgumentsPage(pageNum,dlgfig,dlgdata,pageAction) %#ok<INUSL>

% prepare some needed data
Children = dlgdata.pageData{pageNum}.children;
data = dlgdata.data;

switch pageAction
    case 'updateModelPushButton'
        data = FcnUpdateFromModel(dlgdata);
        bModified = true;
    case 'fcnArgsOrderEdit'
        data.functionarglist = deblank(get(Children.fcnArgsOrderEdit,'String'));
        % delete elements that appear twice or more often
        data.functionarglist = FcnCheckArgumentsList(data.functionarglist);
        % remove empty lines and blanks:
        if ~isempty(data.functionarglist)
            data.functionarglist(cellfun('isempty',tl_deblank(data.functionarglist,2))) = [];
        end
        bModified = true;
    case 'addPushButton'
        data = FcnSelectAdditionalArgs(data);
        if ~isempty(data.additionalarguments)
            data.additionalarguments(cellfun('isempty',tl_deblank(data.additionalarguments,2))) = [];
        end
        bModified = true;
    case 'additionalArgsEdit'
        data.additionalarguments = get(Children.additionalArgsEdit,'String');
        % delete elements that appear twice or more often
        data.additionalarguments = FcnCheckArgumentsList(data.additionalarguments);
        % remove empty lines and blanks:
        if ~isempty(data.additionalarguments)
            data.additionalarguments(cellfun('isempty',tl_deblank(data.additionalarguments,2))) = [];
        end
        bModified = true;
    case 'scalInvCheckbox'
        data.unscaledarguments =  get(Children.scalInvCheckbox,'Value');
        bModified = true;
        % update of page necessary -> enable/disable scaling prop edit field
    case 'scalPropEdit'
        data.scalingpropagation =  get(Children.scalPropEdit,'String');
        bModified = true;
    otherwise
        error(['Invalid action ''' pageAction'''']);
end %switch

dlgdata.data = data;
% end of function FcnManageArgumentsPage


%-------------------------------------------------------------------------------
% FcnUpdateArgumentsPage updates the controls of the arguments page.
%   Function is called after FcnCreateArgumentsPage and by FcnManageArgumentsPage
%   in case the dialog has to be updated due to new data
%
% INPUT ARGUMENTS
%   dlgfig      handle of figure
%   dlgdata     dialog data
%   pageNum     number of page
%
% OUTPUT ARGUMENTS
%   - / -
%-------------------------------------------------------------------------------
function FcnUpdateArgumentsPage(dlgfig,dlgdata,pageNum)

% early return if children are missing
Children = dlgdata.pageData{pageNum}.children;
if isempty(Children),
    return
end; %if

bIsAutosar = dlgdata.data.autosar.isrunnable || dlgdata.data.autosar.isoperationcall;
if bIsAutosar && any(dlgdata.extdata.codegenmode == [0 2]) && ~dlgdata.extdata.bIsEditMode
    % AUTOSAR mode is activated, disable all output controls
    ctrlsList = fieldnames(Children);
    ctrlsList = ctrlsList(cellfun('isempty', regexp(ctrlsList, 'Autosar', 'match')));
    for k = 1:numel(ctrlsList)
        eval(['hChild = Children.', ctrlsList{k}, ';']);
        % There are some control names which are associated to more than
        % one handle. Thus use following loop.
        for m = 1:numel(hChild)
            tmpUserData = get(hChild(m), 'UserData');
            tmpUserData.ctrlStatus.enable = 'off';
            set(hChild(m), 'UserData', tmpUserData);
        end
    end
else
    % invoke standard update function
    if dlgdata.bIsFullVs
        enableOn = 'on';
        enableEdit = 'on';
    else
        enableOn = 'off';
        enableEdit = 'inactive';
    end
    
    % default control status for controls
    fcnArgsOrderEditCtrlStatus      = struct('enable', enableEdit, 'string', '');
    scalPropEditCtrlStatus          = struct('enable', enableEdit, 'string', '');
    scalInvCheckboxCtrlStatus       = struct('enable', enableOn, 'value', 0);
    updateModelPushButtonCtrlStatus = struct('enable', enableOn, 'value', 0); %#ok<NASGU>
    addPushButtonCtrlStatus         = struct('enable', enableOn, 'value', 0); %#ok<NASGU>
    additionalArgsEditCtrlStatus    = struct('enable', enableEdit, 'string', '');
    
    % enable/disable all controls
    fcnArgsOrderEditCtrlStatus.string = dlgdata.data.functionarglist;
    if ~dlgdata.data.unscaledarguments
        % overwrite enable status
        scalPropEditCtrlStatus.enable = 'inactive';
    end
    scalPropEditCtrlStatus.string = dlgdata.data.scalingpropagation;
    scalInvCheckboxCtrlStatus.value = dlgdata.data.unscaledarguments;
    additionalArgsEditCtrlStatus.string = dlgdata.data.additionalarguments;
    
    % write back control status of extra controls to the controls'
    % UserData property
    ctrlsList = {
        'fcnArgsOrderEdit' ...
        'scalPropEdit' ...
        'scalInvCheckbox' ...
        'updateModelPushButton' ...
        'addPushButton' ...
        'additionalArgsEdit'};
    for ctrlsNo=1:length(ctrlsList)
        ctrl = Children.(ctrlsList{ctrlsNo});
        UserData = get(ctrl, 'UserData');
        UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
        set(ctrl, 'UserData', UserData);
    end
end
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);
% end of function FcnUpdateArgumentsPage


%-------------------------------------------------------------------------------
% FcnUpdateFromModel manages "Update from Model" button on arguments page. Function deletes
%   wrong elements from arglist and adds elements that do not already exist.
%
% INPUT ARGUMENTS
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   data        modified data
%-------------------------------------------------------------------------------
function data = FcnUpdateFromModel(dlgdata)

data = dlgdata.data;

% get old list directly from uicontrol
hSystem = get_param(get_param(dlgdata.model,'Parent'),'Handle');
multiLineStr = char(data.functionarglist);
if isempty(multiLineStr),
    %old functionarglist is empty
    argList = {};
else
    % Create cell array of strings of old functionarglist
    argList = cellstr(multiLineStr);
end; %if

% get in-/outports of the subsystem and write them in portList
portList = {};
% inports
hInports =  find_system(hSystem, ...
    'SearchDepth',          1, ...
    'FollowLinks',          'on', ...
    'LookUnderMasks',       'all', ...
    'BlockType',            'Inport');
if ~isempty(hInports),
    portList = [portList;cellstr(get_param(hInports,'name'))];
end; %if
% and outports
hOutports = find_system(hSystem, ...
    'SearchDepth',          1, ...
    'FollowLinks',          'on', ...
    'LookUnderMasks',       'all', ...
    'BlockType',            'Outport');
if ~isempty(hOutports),
    portList = [portList;cellstr(get_param(hOutports,'name'))];
end; %if

% get additional pointer parameters which are defined in additionalarguments property
% and prepend the keyword "$AdditionalParam:" (needed to distinguish from other parameters)
additionalArgList = {};
for elem = 1:length(data.additionalarguments)
    additionalArgList = [additionalArgList; {['AdditionalParam:', data.additionalarguments{elem}]}];    %#ok
end

% Supplement list with placeholder for instance struct.
bReuse = data.forcereuse;
if bReuse,
    portList = [portList;{'$InstanceStruct'}];
end; %if

% elements of both lists (portlist and additionalArgList) are added as long as they don't
% already exist
fullList = [portList; additionalArgList];
% Remove obsolete entries from old arglist: Only members of the fullList (i.e. inports,
% outports, $InstanceStruct, additional pointer arguments defined in additionalarguments)
% and $EVENTS, $RTOSEVENTS, $PARAMETERS are allowed.
% Also possible: $INPUT, $OUTPUT, $DDSTRUCTPOINTERS but these are replaced by the parameters
% in the portlist
allowedEntries = [fullList;{'$events'; '$rtosevents'; '$parameters'; '$ddstructpointers'}];
argList(~ismember(lower(argList),lower(allowedEntries))) = [];
% append new  entries at end of argument list
appIdx = find(~ismember(fullList,argList));
if ~isempty(appIdx),
    argList = [argList;fullList(appIdx)];
end; %if
data.functionarglist = argList;
return
% end of function  FcnUpdateFromModel


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   data = FcnSelectAdditionalArgs(data)
%   Function to manage "Select" button on Arguemnts page. Function opens
%   DD Dialog where Struct-variables can be selected.
%
% INPUT ARGUMENTS
%   data:  dialog data
%
% OUTPUT ARGUMENTS
%   data:     new data
%-------------------------------------------------------------------------------
function data = FcnSelectAdditionalArgs(data)

additionalarguments = data.additionalarguments;
tmpSize = size(additionalarguments);
if tmpSize(1) < tmpSize(2)
    additionalarguments = additionalarguments';
end

% open DD dialog where variables can be selected
filter = {'OnlyRefParamStruct'};
varpath =  dsdd('SelectObject', ...
    ...'CurrentPath',      options.currentPath, ...
    'ObjectKind',       'variable', ...
    filter{:});

% Check if selected dd variable already is a member of the list.
if ~ismember(varpath,additionalarguments)
    % selected variable is not member of the list: add it
    data.additionalarguments = [additionalarguments; cellstr(varpath)];
else
    % selected variable is already in the list: don't add it
end
% end of function FcnSelectAdditionalArgs

%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   newlist = FcnCheckArgumentsList(oldlist)
%   Function to make sure that no entry in list appraers twice. Always the last
%   one is deleted
%
% INPUT ARGUMENTS
%   oldlist:  original arguments list
%
% OUTPUT ARGUMENTS
%   newlist:  list where entries that appear twice are deleted
%-------------------------------------------------------------------------------
function newlist = FcnCheckArgumentsList(oldlist)

if isempty(oldlist)
    newlist = oldlist;
    return
else
    newlist = oldlist(1);
end
for m = 2 : length(oldlist)
    if ~ismember(oldlist(m), newlist)
        newlist = [newlist; oldlist(m)];       %#ok
    end
end
% end of function FcnCheckArgumentsList


%===============================================================================
%
%                                Incremental Page
%
%===============================================================================

%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   [sheetDims,ctrlPos] = FcnIncrementalCtrlPositions(commonGeom, sheetDims)
%   function to calculate positions of blockspecific controls of incremental
%   page. Positions are calculated from the bottom left of the fig to avoid
%   dependencies on figure size.
%
% INPUT ARGUMENTS
%   commonGeom: common geometries like text height, ...
%   sheetDims:  total sheetDims
%
% OUTPUT ARGUMENTS
%   ctrlPos:    position of the controls
%   sheetDims:  total sheetDims of all controls ([width height])
%-------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnIncrementalCtrlPositions(commonGeom, sheetDims)

% get the sizes of the edit fields, checkboxes, buttons and labels (last is
% determined from the longest label)
strings_and_styles = {...
    ' Extract subsystem ',                                            'pushbutton'; ...
    'Export in Simulation-in-the-loop (SIL) mode (generate SIL frame)','radiobutton'; ...
    'Supplement model with stimuli and measurement block',            'checkbox'; ...
    'Destination',                                                    'text'; ...
    repmat('m',1,40),                                                 'edit'; ...
    'List of modules owned by this function (without extension):',    'text'; ...
    repmat('m',1,30),                                                 'edit'; ...
    ' Enable Incremental Code Generation ',                             'checkbox'};
[extrSubSystemPushButtonSize,...
    PILmodeRadiobuttonSize, ...
    suppModelCheckboxSize, ...
    destinationLabelSize, ...
    destinationEditSize, ...
    moduleListLabelSize, ...
    moduleEditBoxSize, ...
    incCodeGenCheckboxSize] = ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% get page partitioning and row/column spacing
widths = [moduleEditBoxSize(1) extrSubSystemPushButtonSize(1)];
[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

% all groupboxes on the page have the same width, which is the maximum of
% the 'needed' width and the width of the page
IncGroupboxWidth = col(end) + colWidth(end) + commonGeom.frameSideEdgeBuffer;
IncGroupboxWidth = max(IncGroupboxWidth, ...
    sheetDims(1) - 2 * commonGeom.sheetSideEdgeBuffer);

% Edit fields such that they fill out the page
destinationEditSize(1) = max(destinationEditSize(1), ...
    IncGroupboxWidth - 2 * commonGeom.frameSideEdgeBuffer);

moduleEditBoxSize(1) = max(moduleEditBoxSize(1), ...
    IncGroupboxWidth - 2 * commonGeom.frameSideEdgeBuffer ...
    - extrSubSystemPushButtonSize(1) - colDelta/3 );
moduleEditBoxSize(2) =  3 * commonGeom.editHeight;

% Position of code coverage option Groupbox
codeCovGroupboxHeight = 3 * PILmodeRadiobuttonSize(2) ...
    + commonGeom.frameTopEdgeBuffer ...
    + commonGeom.frameBottomEdgeBuffer;
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + commonGeom.sheetBottomEdgeBuffer;
ctrlPos.codeCovGroupbox =  [cx,cy,IncGroupboxWidth,codeCovGroupboxHeight];

% Position of decision coverage radiobutton
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.decCovRadiobutton = [cx cy PILmodeRadiobuttonSize];
% Position of statement coverage radiobutton
cy = cy + commonGeom.radiobuttonHeight + rowDelta;
ctrlPos.stateCovRadiobutton = [cx cy PILmodeRadiobuttonSize];
% Position of no code coverage radiobutton
cy = cy + commonGeom.radiobuttonHeight + rowDelta;
ctrlPos.noCovRadiobutton = [cx cy PILmodeRadiobuttonSize];

% Position of Frame generation and subsystem extraction groupbox
frameGenGroupboxHeight = commonGeom.frameTopEdgeBuffer ...
    + 3 * (PILmodeRadiobuttonSize(2) + rowDelta) ...
    + extrSubSystemPushButtonSize(2) + rowDelta ...
    + suppModelCheckboxSize(2) + rowDelta  ...
    + destinationLabelSize(2) ...
    + destinationEditSize(2) ...
    + commonGeom.frameBottomEdgeBuffer;
cx = ctrlPos.codeCovGroupbox(1);
cy = ctrlPos.codeCovGroupbox(2) + codeCovGroupboxHeight ...
    + commonGeom.textHeight;
ctrlPos.frameGenGroupbox =  [cx,cy,IncGroupboxWidth,frameGenGroupboxHeight];

% Position of "Extract subsystem" pushbutton
cx = ctrlPos.frameGenGroupbox(3) - commonGeom.frameSideEdgeBuffer...
    - extrSubSystemPushButtonSize(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.extrSubSystemPushButton = [cx cy extrSubSystemPushButtonSize];

% Position of "Export in PIL mode" radiobutton
cx = col(1);
cy = cy + extrSubSystemPushButtonSize(2) + rowDelta;
ctrlPos.PILmodeRadiobutton = [cx cy PILmodeRadiobuttonSize];
% Position of "Export in PIL mode" radiobutton
cy = cy + PILmodeRadiobuttonSize(2) + rowDelta;
ctrlPos.SILmodeRadiobutton = [cx cy PILmodeRadiobuttonSize];
% Position of "Export in PIL mode" radiobutton
cy = cy + PILmodeRadiobuttonSize(2) + rowDelta;
ctrlPos.MILmodeRadiobutton = [cx cy PILmodeRadiobuttonSize];

% Position of "Supplement model" checkbbox
cy = cy + PILmodeRadiobuttonSize(2) + rowDelta;
ctrlPos.suppModelCheckbox = [cx cy suppModelCheckboxSize];

% Position of destination edit
cy = cy + suppModelCheckboxSize(2) + rowDelta;
ctrlPos.destinationEdit = [cx cy destinationEditSize];

% Position of destination label
cy = cy + destinationEditSize(2);
ctrlPos.destinationLabel = [cx cy destinationLabelSize];

% Position of Incremental code generation groupbox
incCodeGenGroupboxHeight = commonGeom.frameTopEdgeBuffer ...
    + moduleEditBoxSize(2) ...
    + moduleListLabelSize(2) + rowDelta ...
    + incCodeGenCheckboxSize(2) ...
    + commonGeom.frameBottomEdgeBuffer;
cx = ctrlPos.frameGenGroupbox(1);
cy = ctrlPos.frameGenGroupbox(2) + frameGenGroupboxHeight...
    + commonGeom.textHeight;
ctrlPos.incCodeGenGroupbox =  [cx,cy,IncGroupboxWidth,incCodeGenGroupboxHeight];

% Position of "generate code" pushbutton
cx = ctrlPos.incCodeGenGroupbox(3) - commonGeom.frameSideEdgeBuffer...
    - extrSubSystemPushButtonSize(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.genCodePushButton = [cx cy extrSubSystemPushButtonSize];

% Position of "List of modules" edit
cx = col(1);
ctrlPos.moduleListEdit = [cx cy moduleEditBoxSize];
% Position of "List of modules" label
cy = cy + moduleEditBoxSize(2);
ctrlPos.moduleListLabel = [cx cy moduleListLabelSize];
% Position of "incremental code generation" checkbox
cy = cy + moduleListLabelSize(2) + rowDelta;
ctrlPos.incCodeGenCheckbox = [cx cy incCodeGenCheckboxSize];

% Width and height of page
width = IncGroupboxWidth + 2 * commonGeom.sheetSideEdgeBuffer;
height = ctrlPos.codeCovGroupbox(4) ...
    + ctrlPos.frameGenGroupbox(4) ...
    + ctrlPos.incCodeGenGroupbox(4) ...
    + 3 * commonGeom.textHeight ...
    + commonGeom.sheetBottomEdgeBuffer;
sheetDims = [width height];
% end of function FcnIncrementalCtrlPositions


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   dlgdata = FcnCreateIncrementalPage(pageNum,dlgfig,dlgdata)
%   function to create Incremental page. Edit fields and checkboxes are left
%   empty, they are filled out with the block data in the corresponding update
%   function
%
% INPUT ARGUMENTS
%   pageNum:   Number of the page
%   dlgfig:    Handle of Dialog figure
%   dlgdata:   Dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata:   Dialog data (dlgdata.pageData{pageNum}.children new)
%-------------------------------------------------------------------------------
function dlgdata = FcnCreateIncrementalPage(pageNum,dlgfig,dlgdata)

ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;

% Code Coverage groupbox
Children.codeCovGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Code coverage option'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.codeCovGroupbox);

Children.noCovRadiobutton  = uicontrol( ...
    'Parent',             Children.codeCovGroupbox, ...
    'Style',              'radiobutton', ...
    'String',             'No code coverage', ...
    'Position',           ctrlPos.noCovRadiobutton );

Children.stateCovRadiobutton  = uicontrol( ...
    'Parent',             Children.codeCovGroupbox, ...
    'Style',              'radiobutton', ...
    'String',             'Statement coverage', ...
    'Position',           ctrlPos.stateCovRadiobutton );

Children.decCovRadiobutton  = uicontrol( ...
    'Parent',             Children.codeCovGroupbox, ...
    'Style',              'radiobutton', ...
    'String',             'Decision coverage', ...
    'Position',           ctrlPos.decCovRadiobutton );

% Frame generation groupbox?
Children.frameGenGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Frame generation and subsystem extraction'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.frameGenGroupbox);

Children.extrSubSystemPushButton = uicontrol( ...
    'Parent',       Children.frameGenGroupbox, ...
    'Style',        'pushbutton', ...
    'String',       'Extract Subsystem', ...
    'Position',     ctrlPos.extrSubSystemPushButton);

Children.MILmodeRadiobutton  = uicontrol( ...
    'Parent',       Children.frameGenGroupbox, ...
    'Style',        'radiobutton', ...
    'String',       'Export in Model-in-the-loop (MIL) mode (don''t generate frame)', ...
    'Position',     ctrlPos.MILmodeRadiobutton );

Children.SILmodeRadiobutton  = uicontrol( ...
    'Parent',       Children.frameGenGroupbox, ...
    'Style',        'radiobutton', ...
    'String',       'Export in Simulation-in-the-loop (SIL) mode (generate SIL frame)', ...
    'Position',     ctrlPos.SILmodeRadiobutton );

Children.PILmodeRadiobutton  = uicontrol( ...
    'Parent',        Children.frameGenGroupbox, ...
    'Style',         'radiobutton', ...
    'String',        'Export in Processor-in-the-loop (PIL) mode (generate PIL frame)', ...
    'Position',      ctrlPos.PILmodeRadiobutton );

Children.suppModelCheckbox = uicontrol( ...
    'Parent',        Children.frameGenGroupbox, ...
    'Style',         'checkbox', ...
    'String',        'Supplement model with stimuli and measurement block', ...
    'Position',      ctrlPos.suppModelCheckbox);

Children.destinationEdit = uicontrol( ...
    'Parent',         Children.frameGenGroupbox, ...
    'BackGroundColor','w', ...
    'Style',          'edit', ...
    'Position',       ctrlPos.destinationEdit);

Children.destinationLabel = uicontrol( ...
    'Parent',         Children.frameGenGroupbox, ...
    'String',         'Destination:', ...
    'Style',          'text', ...
    'Position',       ctrlPos.destinationLabel);

% Incremental Code Generation Groupbox
Children.incCodeGenGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Incremental code generation'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.incCodeGenGroupbox);

% Here, Max-Min > 0 means that multiple lines can be edited
Children.moduleListEdit = uicontrol( ...
    'Parent',       Children.incCodeGenGroupbox, ...
    'Min',          0, ...
    'Max',          2, ...
    'BackGroundColor','w', ...
    'Style',        'edit', ...
    'Position',     ctrlPos.moduleListEdit);

moduleCMenu = uicontextmenu('Parent', dlgfig);
set(Children.moduleListEdit, 'UIContextMenu', moduleCMenu);
menu.action = uimenu(moduleCMenu, ...
    'Label', 'Create ModuleOwnerShip in DD', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''moduleOwnerShip'')','Incremental'));
set(moduleCMenu, 'UserData', menu);

% enable status is set, because status must not be changed in a locked library
Children.genCodePushButton = uicontrol( ...
    'Parent',       Children.incCodeGenGroupbox, ...
    'Style',        'pushbutton', ...
    'String',       'Generate code', ...
    'enable',       flag2str(dlgdata.data.incrcodegen), ...
    'Position',     ctrlPos.genCodePushButton);

Children.moduleListLabel = uicontrol( ...
    'Parent',        Children.incCodeGenGroupbox, ...
    'String',        'List of modules owned by this function (without extension):', ...
    'Style',         'text', ...
    'Position',      ctrlPos.moduleListLabel);

Children.incCodeGenCheckbox = uicontrol( ...
    'Parent',        Children.incCodeGenGroupbox, ...
    'Style',         'checkbox', ...
    'String',        'Enable Incremental Code Generation', ...
    'Position',      ctrlPos.incCodeGenCheckbox);

dlgdata.pageData{pageNum}.children = Children;
return
% end of function FcnCreateIncrementalPage


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   [dlgdata, bModified] = FcnManageIncrementalPage(pageNum,dlgfig,dlgdata,Action)
%   Function to manage inputs on the Incremental page of the dialog.
%
% INPUT ARGUMENTS
%   pageAction:   depending on which field has been edited
%   dlgfig:       Handle of Dialog figure
%   dlgdata:      Dialog data
%   pageNum:      Number of page
%
% OUTPUT ARGUMENTS
%   dlgdata:      Dialog data
%   bModified:    1 if data has been modified, zero otherwise
%-------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageIncrementalPage(pageNum, dlgfig, dlgdata, Action)

bModified = false;
Children = dlgdata.pageData{pageNum}.children;
data = dlgdata.data;
CovRadiobuttons = [Children.noCovRadiobutton, ...
    Children.stateCovRadiobutton, Children.decCovRadiobutton];
ModeRadiobuttons = [Children.MILmodeRadiobutton, ...
    Children.SILmodeRadiobutton, Children.PILmodeRadiobutton];

switch Action
    case {'noCovRadiobutton','stateCovRadiobutton','decCovRadiobutton'}
        pressedButton = gcbo;
        ds_handle_radiobuttons(CovRadiobuttons,pressedButton);
        data.codecoveragelevel = find(CovRadiobuttons == pressedButton) - 1;
        bModified = true;
        
    case {'MILmodeRadiobutton','SILmodeRadiobutton','PILmodeRadiobutton'}
        pressedButton = gcbo;
        ds_handle_radiobuttons(ModeRadiobuttons,pressedButton);
        data.simmode = find(ModeRadiobuttons == pressedButton);
        bModified = true;
        
    case 'extrSubSystemPushButton'
        FcnExtractSubsystem(dlgdata);
        
    case 'suppModelCheckbox'
        data.addtestframe = get(Children.suppModelCheckbox,'Value');
        bModified = true;
        
    case 'destinationEdit'
        data.destination = tl_deblank(get(Children.destinationEdit,'String'),2);
        bModified = true;
        
    case 'moduleListEdit'
        data.ownedmodules =  get(Children.moduleListEdit,'String');
        % Empty lines from multiline edit controls are removed
        if ~isempty(data.ownedmodules)
            data.ownedmodules(cellfun('isempty',tl_deblank(data.ownedmodules,2))) = [];
        end
        bModified = true;
        
    case 'moduleOwnerShip'
        parentSys = get_param(get_param(dlgdata.model, 'parent'), 'handle');
        hModuleOnwer = tl_check_module_ownership('Systems', getfullname(parentSys));
        if isempty(hModuleOnwer)
            % call TargetLink create function for module owner ships
            tl_check_module_ownership('Systems', parentSys, 'CreateModules', 'on', 'CreateModuleOwnerShip', 'on');
            bModified = true;
        else
            % show selected moduleownership object in current DataDictionary
            dsddman('Select', dsdd('GetAttribute', hModuleOnwer, 'Path'));
        end
        
    case 'genCodePushButton'
        set(dlgfig,'Pointer','watch');
        % apply data befor code generation starts
        tldlg('SystemButtons',dlgfig,'Apply');
        dlgdata = get(dlgfig,'UserData');
        % and generate code
        FcnGenerateCode(dlgdata);
        set(dlgfig,'Pointer','arrow');
        
    case 'incCodeGenCheckbox'
        data.incrcodegen = get(Children.incCodeGenCheckbox,'Value');
        dlgdata.data = data;
        FcnUpdateOptionsPage(dlgfig,dlgdata,1);
        bModified = true;
        
    otherwise
        error(['Invalid control ' Action]);
end %switch
dlgdata.data = data;

% end of function FcnManageIncrementalPage


%-------------------------------------------------------------------------------
% FcnUpdateIncrementalPage updates controls on Incremental page
%
% INPUT ARGUMENTS
%   dlgfig      dialog figure handle
%   pageNum     Number of page
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   - / -
%-------------------------------------------------------------------------------
function FcnUpdateIncrementalPage(dlgfig,dlgdata,pageNum)

% early return if children are missed
Children = dlgdata.pageData{pageNum}.children;
if isempty(Children),
    return
end; %if

data = dlgdata.data;
if dlgdata.bIsFullVs
    enableOn = 'on';
    enableEdit = 'on';
else
    enableOn = 'off';
    enableEdit = 'inactive';
end

parentSys = get_param(get_param(dlgdata.model, 'parent'), 'handle');
if bdroot(dlgdata.model) == parentSys
    enableOnRoot = 'off';
    enableEditOnRoot = 'off';
else
    enableOnRoot = enableOn;
    enableEditOnRoot = enableEdit;
end

if data.incrcodegen
    enableCodeCov = enableOn;
else
    enableCodeCov = 'off';
end

% default control status for controls
genCodePushButtonCtrlStatus = struct('enable', enableOn, 'value', 0);
moduleListEditCtrlStatus    = struct('enable', enableEdit, 'string', '');
moduleCMenu = get(Children.moduleListEdit, 'UIContextMenu');
moduleMenu  = get(moduleCMenu, 'UserData');
incCodeGenCheckboxCtrlStatus = struct('enable', enableOn, 'value', 0);

bIsAutosar = data.autosar.isrunnable || data.autosar.isoperationcall;
if bIsAutosar && any(dlgdata.extdata.codegenmode == [0 2]) && ~dlgdata.extdata.bIsEditMode
    % AUTOSAR mode is activated, disable incremental code generation controls
    moduleListEditCtrlStatus.enable = 'off';
    incCodeGenCheckboxCtrlStatus.enable = 'off';
    % make context menu controls invisible
    menuActionStatus = struct('enable', flag2str(dlgdata.bIsFullVs));
    UserData = get(moduleMenu.action, 'UserData');
    UserData.ctrlStatus = menuActionStatus;
    set(moduleMenu.action, 'UserData', UserData);
else
    % invoke standard update function
    
    % do not change enable status of generate code button, if it is locked
    if ~dlgdata.bLocked
        genCodePushButtonCtrlStatus.enable = flag2str(dlgdata.bIsFullVs && data.incrcodegen);
    end
    if data.incrcodegen
        errStruct = ds_error_get('CurrentState');
        ds_error_none;
        % disable modulelist, if moduleownership exist in current DataDictionary
        if ~dlgdata.bLocked
            % set blockdata temporary, because checkfunction uses blockdata
            % use returnvalue of tl_set to avoid error stack, if block data cannot be set
            err = tl_set(dlgdata.model, 'incrcodegen', data.incrcodegen); %#ok<NASGU>
            err = tl_set(dlgdata.model, 'ownedmodules', data.ownedmodules); %#ok<NASGU>
        end
        hModuleOnwer = tl_check_module_ownership('Systems', getfullname(parentSys));
        if ~dlgdata.bLocked
            % reset temporary blockdata to old blockdata
            % use returnvalue of tl_set to avoid error stack, if block data cannot be set
            err = tl_set(dlgdata.model, 'incrcodegen', dlgdata.olddata.incrcodegen); %#ok<NASGU>
            err = tl_set(dlgdata.model, 'ownedmodules', dlgdata.olddata.ownedmodules); %#ok<NASGU>
        end
        bModuleEnabled = isempty(hModuleOnwer);
        if ~isempty(hModuleOnwer)
            % get module list of owned module
            moduleList = tl_get_owned_modules(hModuleOnwer);
            msgList = ds_error_get('AllMessages');
            if ~isempty(msgList)
                if any([msgList.number] == 4412)
                    % overwrite bModuleEnabled, because inconsistent settings. Modulelist must be enabled.
                    bModuleEnabled = true;
                else
                    % set module list on blockdata
                    data.ownedmodules = {moduleList.name};
                end
            end
            ds_error_merge(errStruct);
        end
    else
        bModuleEnabled = true;
    end
    
    % set context menu controls
    if bModuleEnabled
        menuActionStatus = struct('enable', enableOn, 'Label', 'Create ModuleOwnerShip in DD');
    else
        menuActionStatus = struct('enable', enableOn, 'Label', 'Show ModuleOwnerShip in DD');
    end
    UserData = get(moduleMenu.action, 'UserData');
    UserData.ctrlStatus = menuActionStatus;
    set(moduleMenu.action, 'UserData', UserData);
    moduleListEditCtrlStatus.string = data.ownedmodules;
    moduleListEditCtrlStatus.enable = flag2str(dlgdata.bIsFullVs && bModuleEnabled);
    set(moduleCMenu, 'UserData', moduleMenu);
    incCodeGenCheckboxCtrlStatus.value = data.incrcodegen;
end
dlgdata.data = data;

noCovRadiobuttonCtrlStatus = struct('enable', enableCodeCov, 'value', 0);
stateCovRadiobuttonCtrlStatus = struct('enable', enableCodeCov, 'value', 0);
decCovRadiobuttonCtrlStatus = struct('enable', enableCodeCov, 'value', 0);
extrSubSystemPushButtonCtrlStatus = struct('enable', enableOnRoot, 'value', 0); %#ok<NASGU>
MILmodeRadiobuttonCtrlStatus = struct('enable', enableOnRoot, 'value', 0);
SILmodeRadiobuttonCtrlStatus = struct('enable', enableOnRoot, 'value', 0);
PILmodeRadiobuttonCtrlStatus = struct('enable', enableOnRoot, 'value', 0);
suppModelCheckboxCtrlStatus = struct('enable', enableOnRoot, 'value', 0);
destinationEditCtrlStatus = struct('enable', enableEditOnRoot, 'string', '');

noCovRadiobuttonCtrlStatus.value = (data.codecoveragelevel==0);
stateCovRadiobuttonCtrlStatus.value = (data.codecoveragelevel==1);
decCovRadiobuttonCtrlStatus.value = (data.codecoveragelevel==2);
MILmodeRadiobuttonCtrlStatus.value = (data.simmode==1);
SILmodeRadiobuttonCtrlStatus.value = (data.simmode==2);
PILmodeRadiobuttonCtrlStatus.value = (data.simmode==3);
suppModelCheckboxCtrlStatus.value = data.addtestframe;
% make string single-line, because edit control can not have multi-line text
destination  = strrep(data.destination, char(10),' ');
destinationEditCtrlStatus.string = destination;

% write back control status of extra controls to the controls'
% UserData property
ctrlsList = {
    'noCovRadiobutton'
    'stateCovRadiobutton'
    'decCovRadiobutton'
    'extrSubSystemPushButton'
    'MILmodeRadiobutton'
    'SILmodeRadiobutton'
    'PILmodeRadiobutton'
    'suppModelCheckbox'
    'destinationEdit'
    'moduleListEdit'
    'genCodePushButton'
    'incCodeGenCheckbox'};
for ctrlsNo=1:length(ctrlsList)
    ctrl = Children.(ctrlsList{ctrlsNo});
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = eval([ctrlsList{ctrlsNo} 'CtrlStatus']);
    set(ctrl, 'UserData', UserData);
end
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);
% end of function FcnUpdateIncrementalPage


%===============================================================================
%
%                                 AUTOSAR Page
%
%===============================================================================

%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   [sheetDims,ctrlPos] = FcnAutosarCtrlPosition(commonGeom,sheetDims)
%   function to calculate positions of blockspecific controls of AUTOSAR
%   page. Positions are calculated from the bottom left of the fig to avoid
%   dependencies on figure size.
%
% INPUT ARGUMENTS
%   commonGeom: common geometries like text height, ...
%   sheetDims:  total sheetDims
%
% OUTPUT ARGUMENTS
%   ctrlPos:    position of the controls
%   sheetDims:  total sheetDims of all controls ([width height])
%-------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnAutosarCtrlPositions(commonGeom,sheetDims)

% Get the sizes of the edit fields, checkboxes, buttons and labels (last is
% determined from the longest label).
strings_and_styles = {
    repmat('m',1,40),           'checkbox'; ...
    'Restart function name:',   'text'; ...
    repmat('m',1,30),           'edit'; ...
    'n',                        'pushbutton'; ...
    'Force',                    'checkbox'; ...
    '  Show RTE events ... ',   'pushbutton'};
[isRunnableCheckboxSize, ...
    labelSize, ...
    editSize, ...
    dotPushButtonSize, ...
    forceCheckboxSize, ...
    buttonSize] = ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% correct height, because on some platforms icon overlapped button boundary; icon height is 18 pixel.
dotPushButtonSize(2) = max(22, dotPushButtonSize(2));

% Get the page partitioning and row/column spacing.
widths = [labelSize(1) editSize(1) forceCheckboxSize(1)];
[col,colWidth,colDelta,rowDelta] = ds_get_gui_columns(widths,commonGeom);

maxEditWidth = colWidth(2)+colWidth(3)+colDelta/3;
classEditSize = [maxEditWidth-2*dotPushButtonSize(1), editSize(2)];
dotButtonSize = [2*dotPushButtonSize(1) dotPushButtonSize(2)];

% All groupboxes on this page have the same width, which is the maximum of
% the 'needed' width and the size of the page.
runnableGroupboxWidth = col(end) ...
    + colWidth(end) ...
    + commonGeom.frameSideEdgeBuffer;
runnableGroupboxWidth = max(runnableGroupboxWidth, ...
    sheetDims(1) - 2 * commonGeom.sheetSideEdgeBuffer);

% Position of SIL/PIL simulation groupbox.
simulationGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + editSize(2) ...
    + commonGeom.frameBottomEdgeBuffer;
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = commonGeom.bottomSheetOffset + commonGeom.sheetBottomEdgeBuffer;
ctrlPos.simulationGroupbox = [cx, cy, runnableGroupboxWidth, simulationGroupboxHeight];

% Position of is implemented for SIL simulation checkbox
cx = col(1);
cy = commonGeom.frameBottomEdgeBuffer;
ctrlPos.SILsimulationCheckbox = [cx cy isRunnableCheckboxSize];

% Position of operation call groupbox.
operationCallGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + 3 * editSize(2) + 2 * rowDelta ...
    + commonGeom.frameBottomEdgeBuffer;
cx = ctrlPos.simulationGroupbox(1);
cy = ctrlPos.simulationGroupbox(2) + ctrlPos.simulationGroupbox(4) ...
    + commonGeom.textHeight;
ctrlPos.operationCallGroupbox = [cx, cy, runnableGroupboxWidth, operationCallGroupboxHeight];

% Position of "operation" controls
cy = commonGeom.frameBottomEdgeBuffer;
cx = col(1);
ctrlPos.operationLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.operationEdit = [cx cy classEditSize];
% select button
cx = col(3);
ctrlPos.operationSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.operationMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

% Position of client port controls
cx = col(1);
cy = cy + commonGeom.editHeight + rowDelta;
ctrlPos.clientPortLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.clientPortEdit = [cx cy classEditSize];
% select button
cx = col(3);
ctrlPos.clientPortSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.clientPortMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

% Position of server-operation checkbox
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.operationCallCheckbox = [cx cy isRunnableCheckboxSize];

% Position of runnable groupbox.
runnableGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + 5 * editSize(2) + 5 * rowDelta ...
    + 5 * commonGeom.textHeight ...
    + commonGeom.frameBottomEdgeBuffer;
cx = ctrlPos.operationCallGroupbox(1);
cy = ctrlPos.operationCallGroupbox(2) + ctrlPos.operationCallGroupbox(4) ...
    + commonGeom.textHeight;
ctrlPos.runnableGroupbox = [cx,cy,runnableGroupboxWidth,runnableGroupboxHeight];

% Position of show event button
cy = commonGeom.frameBottomEdgeBuffer;
cx = col(1);
ctrlPos.showEventButton = [cx cy buttonSize];

% Position of runnable properties groupbox
RunnablePropsGroupboxHeight = ...
    commonGeom.frameTopEdgeBuffer ...
    + 5 * commonGeom.textHeight ...
    + commonGeom.frameBottomEdgeBuffer;
RunnablePropsGroupboxWidth = runnableGroupboxWidth ...
    - 2 * commonGeom.frameSideEdgeBuffer;
cy = cy + editSize(2) + rowDelta;
ctrlPos.RunnablePropsGroupbox = [cx,cy,RunnablePropsGroupboxWidth,RunnablePropsGroupboxHeight];
textSize = [RunnablePropsGroupboxWidth-commonGeom.frameSideEdgeBuffer-col(2) commonGeom.textHeight];

% Position of text controls
cy = commonGeom.frameBottomEdgeBuffer;
cx = col(1);
ctrlPos.moduleLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.moduleText = [cx cy textSize];

cy = cy + textSize(2);
cx = col(1);
ctrlPos.classLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.classText = [cx cy textSize];

cy = cy + textSize(2);
cx = col(1);
ctrlPos.nameLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.nameText = [cx cy textSize];

cy = cy + textSize(2);
cx = col(2);
ctrlPos.descriptionText = [cx cy textSize(1) 2*textSize(2)];
cy = cy + textSize(2);
cx = col(1);
ctrlPos.descriptionLabel = [cx cy labelSize];

% Position of runnable controls
cx = col(1);
cy = ctrlPos.showEventButton(2) + ctrlPos.showEventButton(4) + RunnablePropsGroupboxHeight + 2*rowDelta;
ctrlPos.runnableLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.runnableEdit = [cx cy classEditSize];
% select button
cx = col(3);
ctrlPos.runnableSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.runnableMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

% Position of swc controls
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.swcLabel = [cx cy labelSize];
cx = col(2);
ctrlPos.swcEdit = [cx cy classEditSize];
% select button
cx = col(3);
ctrlPos.swcSelectButton = [cx,cy, dotButtonSize];
% menu button
cx = cx + dotPushButtonSize(1);
ctrlPos.swcMenuButton = [cx+2,cy+2,dotPushButtonSize(1)-4 dotPushButtonSize(2)-4];

% Position of AUTOSAR checkbox
cx = col(1);
cy = cy + editSize(2) + rowDelta;
ctrlPos.isRunnableCheckbox = [cx cy isRunnableCheckboxSize];

% Width and height of page.
width = runnableGroupboxWidth + 2 * commonGeom.sheetSideEdgeBuffer;
height = ...
    + ctrlPos.runnableGroupbox(4) ...
    + ctrlPos.operationCallGroupbox(4) ...
    + ctrlPos.simulationGroupbox(4) ...
    + 3 * commonGeom.textHeight ...
    + commonGeom.sheetBottomEdgeBuffer;

textWidth = runnableGroupboxWidth;
textHeight = 2 * commonGeom.textHeight;

%--------------------------------------------------------------------------
% 1st row
cx = commonGeom.figSideEdgeBuffer + commonGeom.sheetSideEdgeBuffer;
cy = ctrlPos.runnableGroupbox(2) + ctrlPos.runnableGroupbox(4) ...
    + commonGeom.textHeight;

% dualEditText frame
ctrlPos.dualEditText = [cx, cy, textWidth, textHeight];
height = height + textHeight + commonGeom.textHeight;

width = max(width, sheetDims(1));
height = max(height, sheetDims(2));
sheetDims = [width, height];
% end of function FcnAutosarCtrlPosition


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   dlgdata = FcnCreateAutosarPage(pageNum,dlgfig,dlgdata)
%   function to create the Options page. Edit fields and checkboxes are left
%   empty, they are filled out with the block data in the update function
%
% INPUT ARGUMENTS
%   pageNum:   Number of the page
%   dlgfig:    Handle of Dialog figure
%   dlgdata:   Dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata:   Dialog data (dlgdata.pageData{pageNum}.children new)
%-------------------------------------------------------------------------------
function dlgdata = FcnCreateAutosarPage(pageNum,dlgfig,dlgdata)

ctrlPos = dlgdata.pageData{pageNum}.ctrlPos;
pageName   = dlgdata.pageNames{pageNum};
defColor = get(0, 'DefaultUIControlBackgroundColor');

userDataMenuButton.cDataEnabled  = tl_get_icon('ArrowHeadDown_10x18', 'BackgroundColor', defColor);
userDataMenuButton.cDataDisabled = tl_get_icon('ArrowHeadDown_10x18_disabled');
userDataSelectButton.cDataEnabled  = tl_get_icon('Browse_Seperator_24x18', 'BackgroundColor', defColor);
userDataSelectButton.cDataDisabled = tl_get_icon('Browse_Seperator_24x18');

% get software component path from runnable settings
dlgdata.swcPath = FcnGetSoftwareComponent(dlgdata.model, dlgdata.data.autosar);

% create dualEditText
Children.dualEditText = uicontrol( ...
    'Parent',             dlgfig, ...
    'Style',              'text', ...
    'Position',           ctrlPos.dualEditText);

% AUTOSAR code options groupbox
Children.runnableGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Runnable code options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.runnableGroupbox);

% use AUTOSAR checkbox
Children.isRunnableCheckbox = uicontrol( ...
    'Parent',   Children.runnableGroupbox, ...
    'Style',    'checkbox', ...
    'String',   'Implement subsystem as runnable', ...
    'Position', ctrlPos.isRunnableCheckbox);

% SWC
Children.swcLabel = uicontrol( ...
    'Parent',   Children.runnableGroupbox, ...
    'Style',    'text', ...
    'String',   'Software component:', ...
    'Position', ctrlPos.swcLabel);

Children.swcEdit = uicontrol( ...
    'Parent',   Children.runnableGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.swcEdit);

Children.swcSelectButton = uicontrol( ...
    'Parent',            Children.runnableGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.swcSelectButton);

Children.swcMenuButton = uicontrol( ...
    'Parent',            Children.runnableGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.swcMenuButton);

swcCMenu = uicontextmenu('Parent', dlgfig);
set(Children.swcEdit, 'UIContextMenu', swcCMenu);
set(Children.swcMenuButton, 'UIContextMenu', swcCMenu);
menu.select = uimenu(swcCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''swcSelectButton'')',pageName));
menu.show = uimenu(swcCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''swcShowDDObject'')',pageName), ...
    'Separator','on');
set(swcCMenu, 'UserData', menu);

% runnable
Children.runnableLabel = uicontrol( ...
    'Parent',   Children.runnableGroupbox, ...
    'Style',    'text', ...
    'String',   'Runnable:', ...
    'Position', ctrlPos.runnableLabel);

Children.runnableEdit = uicontrol( ...
    'Parent',   Children.runnableGroupbox, ...
    'Style',    'edit', ...
    'Position', ctrlPos.runnableEdit);

Children.runnableSelectButton = uicontrol( ...
    'Parent',            Children.runnableGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.runnableSelectButton);

Children.runnableMenuButton = uicontrol( ...
    'Parent',            Children.runnableGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.runnableMenuButton);

runnableCMenu = uicontextmenu('Parent', dlgfig);
set(Children.runnableEdit, 'UIContextMenu', runnableCMenu);
set(Children.runnableMenuButton, 'UIContextMenu', runnableCMenu);
menu.select = uimenu(runnableCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''runnableSelectButton'')',pageName));
menu.show = uimenu(runnableCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''runnableShowDDObject'')',pageName), ...
    'Separator','on');
set(runnableCMenu, 'UserData', menu);

% AUTOSAR code runnable properties groupbox
Children.RunnablePropsGroupbox = uipanel( ...
    'Parent',            Children.runnableGroupbox, ...
    'Title',            {'Runnable properties'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.RunnablePropsGroupbox);

% text controls
Children.descriptionLabel = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'Description:', ...
    'Position', ctrlPos.descriptionLabel);

Children.descriptionText = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   ' ', ...
    'Position', ctrlPos.descriptionText);

Children.nameLabel = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'Name:', ...
    'Position', ctrlPos.nameLabel);

Children.nameText = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'controller_runnable', ...
    'Position', ctrlPos.nameText);

Children.classLabel = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'Function class:', ...
    'Position', ctrlPos.classLabel);

Children.classText = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'GLOBAL_FCN', ...
    'Position', ctrlPos.classText);

Children.moduleLabel = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'Module:', ...
    'Position', ctrlPos.moduleLabel);

Children.moduleText = uicontrol( ...
    'Parent',   Children.RunnablePropsGroupbox, ...
    'Style',    'text', ...
    'String',   'controller', ...
    'Position', ctrlPos.moduleText);

Children.showEventButton = uicontrol( ...
    'Parent',   Children.runnableGroupbox, ...
    'Style',    'pushbutton', ...
    'String',   ' Show RTE Events ... ', ...
    'Position', ctrlPos.showEventButton);

% operation call groupbox
Children.operationCallGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Operation call code options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.operationCallGroupbox);

% operation call checkbox
Children.operationCallCheckbox = uicontrol( ...
    'Parent',   Children.operationCallGroupbox, ...
    'Style',    'checkbox', ...
    'enable',   'on', ...
    'String',   'Implement subsystem as operation call', ...
    'Position', ctrlPos.operationCallCheckbox);

Children.clientPortLabel = uicontrol( ...
    'Parent',   Children.operationCallGroupbox, ...
    'Style',    'text', ...
    'enable',   'on', ...
    'String',   'Client port:', ...
    'Position', ctrlPos.clientPortLabel);

Children.clientPortEdit = uicontrol( ...
    'Parent',   Children.operationCallGroupbox, ...
    'Style',    'edit', ...
    'enable',   'on', ...
    'Position', ctrlPos.clientPortEdit);

Children.clientPortSelectButton = uicontrol( ...
    'Parent',            Children.operationCallGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.clientPortSelectButton);

Children.clientPortMenuButton = uicontrol( ...
    'Parent',            Children.operationCallGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.clientPortMenuButton);

clientPortCMenu = uicontextmenu('Parent', dlgfig);
set(Children.clientPortEdit, 'UIContextMenu', clientPortCMenu);
set(Children.clientPortMenuButton, 'UIContextMenu', clientPortCMenu);
menu.select = uimenu(clientPortCMenu, ...
    'Label',    'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''clientPortSelectButton'')',pageName));
menu.show = uimenu(clientPortCMenu, ...
    'Label',    'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''clientPortShowDDObject'')',pageName), ...
    'Separator','on');
set(clientPortCMenu, 'UserData', menu);

% runnable
Children.operationLabel = uicontrol( ...
    'Parent',   Children.operationCallGroupbox, ...
    'Style',    'text', ...
    'enable',   'on', ...
    'String',   'Operation:', ...
    'Position', ctrlPos.operationLabel);

Children.operationEdit = uicontrol( ...
    'Parent',   Children.operationCallGroupbox, ...
    'enable',   'on', ...
    'Style',    'edit', ...
    'Position', ctrlPos.operationEdit);

Children.operationSelectButton = uicontrol( ...
    'Parent',            Children.operationCallGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataSelectButton, ...
    'CData',             userDataSelectButton.cDataEnabled, ...
    'Position',          ctrlPos.operationSelectButton);

Children.operationMenuButton = uicontrol( ...
    'Parent',            Children.operationCallGroupbox, ...
    'Style',             'pushbutton', ...
    'UserData',          userDataMenuButton, ...
    'CData',             userDataMenuButton.cDataEnabled, ...
    'Position',          ctrlPos.operationMenuButton);

operationCMenu = uicontextmenu('Parent', dlgfig);
set(Children.operationEdit, 'UIContextMenu', operationCMenu);
set(Children.operationMenuButton, 'UIContextMenu', operationCMenu);
menu.select = uimenu(operationCMenu, ...
    'Label', 'Select', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''operationSelectButton'')',pageName));
menu.show = uimenu(operationCMenu, ...
    'Label', 'Show in DD Manager', ...
    'Callback', sprintf('tldlg(''%s'',gcbf,''operationShowDDObject'')',pageName), ...
    'Separator','on');
set(operationCMenu, 'UserData', menu);

% operation call groupbox
Children.simulationGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'SIL/PIL simulation options'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.simulationGroupbox);

% is implemented for SIL simulation checkbox
Children.SILsimulationCheckbox = uicontrol( ...
    'Parent',   Children.simulationGroupbox, ...
    'Style',    'checkbox', ...
    'String',   'Use this subsystem for SIL/PIL simulation', ...
    'Position', ctrlPos.SILsimulationCheckbox);

dlgdata.pageData{pageNum}.children = Children;
% end of function FcnCreateAutosarPage


%-----------------------------------------------------------------------------------------
% FcnManageAutosarPage manages control actions of autosar page
%
% INPUT ARGUMENTS
%   pageNum      number of tab
%   dlgdata      dialog data
%   pageAction   action at one control of current page
%
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageAutosarPage(pageNum, dlgdata, pageAction)

% prepare needed data
bModified  = 0;
Children   = dlgdata.pageData{pageNum}.children;
swcRoot = '/Pool/Autosar/SoftwareComponents';
interfaceRoot = 'Pool/Autosar/Interfaces';

switch pageAction
    case 'isRunnableCheckbox'
        dlgdata.data.autosar.isrunnable = get(Children.isRunnableCheckbox,'Value');
        bModified = true;
        
    case 'swcEdit'
        swcString = get(Children.swcEdit,'String');
        bModified = true;
        idxPorts = strfind(swcString, '/SoftwareComponents/');
        if ~isempty(idxPorts)
            % save only port name
            swcString = swcString(idxPorts+20:end);
        end
        dlgdata.data.autosar.softwarecomponent = swcString;
        
    case {'swcMenuButton' 'runnableMenuButton'},
        panelPos = get(Children.runnableGroupbox, 'Position');
        FcnSetMenuPosition(Children.(pageAction), panelPos(1:2));
        bModified = 1;
        
    case 'swcSelectButton',
        bModified = true;
        swcPath = dlgdata.data.autosar.softwarecomponent;
        swcPath = dsdd( 'SelectObject', ...
            'CurrentPath', swcPath, ...
            'EntryPath', swcRoot, ...
            'ObjectKind','SoftwareComponent');
        if ~isempty(swcPath)
            dlgdata.data.autosar.softwarecomponent = swcPath;
        end
        
    case 'swcShowDDObject',
        if ~isempty(dlgdata.data.autosar.softwarecomponent)
            swcPath = [swcRoot '/' dlgdata.data.autosar.softwarecomponent];
            dsddman('Select', swcPath);
        else
            dsddman('Select', swcRoot);
        end
        
    case 'runnableEdit'
        runnableString = get(Children.runnableEdit,'String');
        bModified = true;
        idxRunnable = strfind(runnableString, '/Runnables/');
        if ~isempty(idxRunnable)
            % save only runnable name
            runnableString = runnableString(idxRunnable+11:end);
        end
        dlgdata.data.autosar.runnable = runnableString;
        
    case 'runnableSelectButton'
        bModified = true;
        % runnable select button is only available if softwarecomponent is set
        swcPath = [swcRoot '/' dlgdata.data.autosar.softwarecomponent '/Runnables'];
        % get runnable name
        runnablePath = dlgdata.data.autosar.runnable;
        runnablePath = dsdd( 'SelectObject', ...
            'CurrentPath', runnablePath, ...
            'EntryPath', swcPath, ...
            'ObjectKind', 'Runnable');
        if ~isempty(runnablePath)
            dlgdata.data.autosar.runnable = runnablePath;
        end
        
    case 'runnableShowDDObject',
        swcPath = [swcRoot '/' dlgdata.data.autosar.softwarecomponent];
        if ~isempty(dlgdata.data.autosar.runnable)
            dsddman('Select', [swcPath '/Runnables/' dlgdata.data.autosar.runnable]);
        else
            dsddman('Select', swcPath);
        end
        
    case 'showEventButton'
        swcPath = [swcRoot '/' dlgdata.data.autosar.softwarecomponent];
        runnablePath = [swcPath '/Runnables/' dlgdata.data.autosar.runnable];
        hDDRunnable = dsdd('GetAttribute', runnablePath, 'hDDObject');
        eventRoot = [swcPath '/RteEvents'];
        hRteEvents = dsdd('Find',eventRoot,'objectkind','RteEvent');
        rteEventInfo = '';
        for k = 1 : numel(hRteEvents)
            if dsdd('GetRunnableRefTarget', hRteEvents(k)) == hDDRunnable
                % add RTE event info
                evName = dsdd('GetAttribute', hRteEvents(k), 'name');
                evKind = dsdd('GetRteEventKind', hRteEvents(k));
                evPort = dsdd('GetReceiverPortRef', hRteEvents(k));
                if ~isempty(evPort)
                    evPort = ['; Port: ' evPort]; %#ok<AGROW>
                end
                evElem = dsdd('GetDataElementRef', hRteEvents(k));
                if ~isempty(evElem)
                    idx = strfind(evElem, '/');
                    evElem = ['; Data element: ' evElem(idx(end)+1:end)];
                end
                evTime = dsdd('GetPeriod', hRteEvents(k));
                if ~isempty(evTime)
                    evTime = ['; Sample time: ' num2str(evTime)];
                end
                evOp = dsdd('GetOperationRef', hRteEvents(k));
                if ~isempty(evOp)
                    idx = strfind(evOp, '/');
                    evOp = ['; Operation: ' evOp(idx(end)+1:end)];
                end
                evMode = dsdd('GetModeElementRef', hRteEvents(k));
                if ~isempty(evMode)
                    idx = strfind(evMode, '/');
                    evMode = ['; Mode element: ' evMode(idx(end)+1:end)];
                end
                rteEventInfo.(evName) = [evKind evPort evElem evTime evOp evMode];
            end
        end
        if isempty(hRteEvents) || isempty(rteEventInfo)
            rteEventInfo.events = 'none';
        end
        % open additional window with list of RTE events
        tl_showdlg(rteEventInfo,Children.showEventButton, 'RTE events');
        
    case 'operationCallCheckbox'
        dlgdata.data.autosar.isoperationcall = get(Children.operationCallCheckbox,'Value');
        bModified = true;
        
    case 'clientPortEdit'
        portString = get(Children.clientPortEdit,'String');
        bModified = true;
        idxPorts = strfind(portString, '/Ports/');
        if ~isempty(idxPorts)
            % save only port name
            portString = portString(idxPorts+7:end);
        end
        dlgdata.data.autosar.clientport = portString;
        
    case {'clientPortMenuButton' 'operationMenuButton'},
        panelPos = get(Children.operationCallGroupbox, 'Position');
        FcnSetMenuPosition(Children.(pageAction), panelPos(1:2));
        bModified = 1;
        
    case 'clientPortSelectButton',
        bModified = true;
        
        swcPath = dlgdata.swcPath;
        portPath = dlgdata.data.autosar.clientport;
        if ~isempty(swcPath)
            portPath = [swcRoot '/' swcPath '/Ports/' portPath];
        end
        
        portPath = dsdd( 'SelectObject', ...
            'CurrentPath', portPath, ...
            'EntryPath', swcRoot, ...
            'ObjectKind', 'ClientPort');
        idxPorts = strfind(portPath, '/Ports/');
        if ~isempty(idxPorts)
            % save only port name
            portPath = portPath(idxPorts+7:end);
        end
        dlgdata.data.autosar.clientport = portPath;
        
    case 'clientPortShowDDObject',
        if ~isempty(dlgdata.data.autosar.clientport)
            swcPath = dlgdata.swcPath;
            if ~isempty(swcPath)
                swcRoot = [swcRoot '/' swcPath '/Ports/'];
            end
            dsddman('Select', [swcRoot dlgdata.data.autosar.clientport]);
        else
            dsddman('Select', swcRoot);
        end
        
    case 'operationEdit'
        operationString = get(Children.operationEdit,'String');
        bModified = true;
        idxInterfaces = strfind(operationString, '/Operations/');
        if ~isempty(idxInterfaces)
            % do not save standard interface path
            operationString = operationString(idxInterfaces+12:end);
        end
        dlgdata.data.autosar.operation = operationString;
        
    case 'operationSelectButton'
        bModified = true;
        swcPath = dlgdata.swcPath;
        if ~isempty(swcPath)
            swcRoot = [swcRoot '/' swcPath];
        end
        portPath = dlgdata.data.autosar.clientport;
        if ~isempty(portPath)
            portPath = [swcRoot '/Ports/' portPath];
            interface = dsdd('GetClientServerInterfaceRefTarget',portPath);
            interfacePath = dsdd('GetAttribute', interface, 'path');
        end
        operationPath = dlgdata.data.autosar.operation;
        if ~isempty(interface)
            operationPath = [interfacePath '/Operations/' operationPath];
        end
        operationPath = dsdd( 'SelectObject', ...
            'CurrentPath', operationPath, ...
            'EntryPath', interfaceRoot, ...
            'ObjectKind', 'Operation');
        idxOperations = strfind(operationPath, '/Operations/');
        if ~isempty(idxOperations)
            % do not save standard operation path
            operationPath = operationPath(idxOperations+12:end);
        end
        dlgdata.data.autosar.operation = operationPath;
        
    case 'operationShowDDObject',
        portPath = [swcRoot '/' dlgdata.swcPath '/Ports/' dlgdata.data.autosar.clientport];
        interface = dsdd('GetClientServerInterfaceRefTarget',portPath);
        interfacePath = dsdd('GetAttribute', interface, 'path');
        operationPath = dlgdata.data.autosar.operation;
        if ~isempty(operationPath)
            dsddman('Select', [interfacePath '/Operations/' operationPath]);
        else
            dsddman('Select', interfaceRoot);
        end
        
    case 'SILsimulationCheckbox'
        dlgdata.data.autosar.isimplementationforsilpil = get(Children.SILsimulationCheckbox,'Value');
        bModified = true;
        
    otherwise
        error(['Invalid control ' pageAction]);
        
end % switch(action)


%-------------------------------------------------------------------------------
% FUNCTION DESCRIPTION
%   FcnUpdateAutosarPage(dlgfig,dlgdata,pageNum)
%   Function to to update controls on AUTOSAR page: Enable/disable controls,
%   write data to edit fields, highlight invalid/inconsistent data.
%   Function is called after FcnCreateAutosarPage and by FcnManageAutosarPage in
%   case the dialog has to be updated due to new data
%
% INPUT ARGUMENTS
%   pageNum:  Number of page
%   dlgdata:  dialog data
%   dlgfig:   Handle of dialog figure
%
% OUTPUT ARGUMENTS
%   dlgdata   updated dialog data
%-------------------------------------------------------------------------------
function dlgdata = FcnUpdateAutosarPage(dlgfig,dlgdata,pageNum)

if dlgdata.extdata.bIsEditMode
    msg = ['   The dual edit mode is active ' char(10) '    to visualize both standard as well as AUTOSAR code generation settings. '];
    set(dlgdata.pageData{pageNum}.children.dualEditText, ...
        'String', msg, ...
        'Enable', 'on', ...
        'ForegroundColor',    'w', ...
        'BackgroundColor',    [.9 .5 0] ...    % orange
        );
else
    set(dlgdata.pageData{pageNum}.children.dualEditText, ...
        'String', ' ', ...
        'ForegroundColor',    'b', ...
        'BackgroundColor',    get(dlgfig,'Color') ...
        );
end

Children = dlgdata.pageData{pageNum}.children;

OFF = 0;
INACTIVE = 1;
ON = 2;
FullVsOn = dlgdata.bIsFullVs + 1;
% default control status for controls of AUTOSAR communication groupbox
% default is 'enabled' for radio buttons and 'disabled' for AUTOSAR settings
isRunnableCheckboxCtrlStatus = struct('enable', FullVsOn, 'value', 0);
swcEditCtrlStatus            = struct('enable', OFF,  'string', '');
swcSelectButtonCtrlStatus    = struct('enable', OFF);
swcMenuButtonCtrlStatus      = struct('enable', OFF);
runnableEditCtrlStatus       = struct('enable', OFF, 'string', '');
runnableSelectButtonCtrlStatus = struct('enable', OFF);
runnableMenuButtonCtrlStatus   = struct('enable', OFF);
operationCheckboxCtrlStatus  = struct('enable', FullVsOn, 'value', 0);
clientPortEditCtrlStatus     = struct('enable', OFF,  'string', '<undefined>');
clientPortSelectButtonCtrlStatus    = struct('enable', OFF);
clientPortMenuButtonCtrlStatus      = struct('enable', OFF);
operationEditCtrlStatus      = struct('enable', OFF, 'string', '<undefined>');
operationSelectButtonCtrlStatus    = struct('enable', OFF);
operationMenuButtonCtrlStatus      = struct('enable', OFF);
descriptionTextCtrlStatus    = struct('enable', OFF, 'string', '');
nameTextCtrlStatus           = struct('enable', OFF, 'string', '');
classTextCtrlStatus          = struct('enable', OFF, 'string', '');
moduleTextCtrlStatus         = struct('enable', OFF, 'string', '');
showEventButtonCtrlStatus    = struct('enable', OFF);
swcCMenu = get(Children.swcEdit, 'UIContextMenu');
swcMenu  = get(swcCMenu, 'UserData');
swcMenuShowStatus           = struct('enable', OFF);
swcMenuSelectStatus         = struct('enable', OFF);
runnableCMenu = get(Children.runnableEdit, 'UIContextMenu');
runnableMenu  = get(runnableCMenu, 'UserData');
runnableMenuShowStatus      = struct('enable', OFF);
runnableMenuSelectStatus    = struct('enable', OFF);
clientPortCMenu = get(Children.clientPortEdit, 'UIContextMenu');
clientPortMenu  = get(clientPortCMenu, 'UserData');
clientPortMenuShowStatus          = struct('enable', OFF);
clientPortMenuSelectStatus        = struct('enable', OFF);
operationCMenu = get(Children.operationEdit, 'UIContextMenu');
operationMenu  = get(operationCMenu, 'UserData');
operationMenuShowStatus     = struct('enable', OFF);
operationMenuSelectStatus   = struct('enable', OFF);
SILsimulationCheckboxCtrlStatus = struct('enable', FullVsOn, 'value', 1);

statusString = '';
if any(dlgdata.extdata.codegenmode == [0 2]) || dlgdata.extdata.bIsEditMode
    data = dlgdata.data.autosar;
    % get software component path from runnable settings
    dlgdata.swcPath = FcnGetSoftwareComponent(dlgdata.model, data);
    
    isRunnableCheckboxCtrlStatus.value = data.isrunnable;
    DSDDManON = dlgdata.bDSDDMan + 1;
    
    swcRoot = '/Pool/Autosar/SoftwareComponents';
    interfaceRoot = '/Pool/Autosar/Interfaces';
    if data.isrunnable
        data.isimplementationforsilpil = 1;
        SILsimulationCheckboxCtrlStatus.enable = INACTIVE;
        
        swcEditCtrlStatus.string = data.softwarecomponent;
        swcEditCtrlStatus.enable = FullVsOn;
        swcSelectButtonCtrlStatus.enable = FullVsOn;
        swcMenuButtonCtrlStatus.enable = FullVsOn;
        swcMenuShowStatus.enable   = DSDDManON;
        swcMenuSelectStatus.enable = FullVsOn;
        if ~isempty(data.softwarecomponent)
            bExist = dsdd('Exist', ...
                [swcRoot '/' data.softwarecomponent], ...
                'ObjectKind', 'SoftwareComponent');
            if bExist
                runnableEditCtrlStatus.string = data.runnable;
                runnableEditCtrlStatus.enable = FullVsOn;
                runnableSelectButtonCtrlStatus.enable = FullVsOn;
                runnableMenuButtonCtrlStatus.enable = FullVsOn;
                runnableMenuShowStatus.enable   = DSDDManON;
                runnableMenuSelectStatus.enable = FullVsOn;
                if ~isempty(data.runnable)
                    runnablePath = [swcRoot '/' data.softwarecomponent '/Runnables/' data.runnable];
                    bExist = dsdd('Exist', ...
                        runnablePath, ...
                        'ObjectKind', 'Runnable');
                    if bExist
                        descriptionTextCtrlStatus.enable = ON;
                        descriptionString = dsdd('GetDescription', runnablePath);
                        if numel(descriptionString) > 60
                            descriptionString = [descriptionString(1:60) char(10) descriptionString(61 : end)];
                        end
                        descriptionTextCtrlStatus.string = descriptionString;
                        nameTextCtrlStatus.enable = ON;
                        nameTextCtrlStatus.string = dsdd('GetNameTemplate', runnablePath);
                        classTextCtrlStatus.enable = ON;
                        classTextCtrlStatus.string = dsdd('GetFunctionClassRef', runnablePath);
                        moduleTextCtrlStatus.enable = ON;
                        moduleTextCtrlStatus.string = dsdd('GetModuleRef', runnablePath);
                        showEventButtonCtrlStatus.enable = ON;
                    else
                        runnableEditCtrlStatus.iserror = 1;
                    end
                end
            else
                swcEditCtrlStatus.iserror = 1;
            end
        end
    end
    
    operationCheckboxCtrlStatus.value = data.isoperationcall;
    
    if data.isoperationcall
        clientPortEditCtrlStatus.enable = FullVsOn;
        clientPortSelectButtonCtrlStatus.enable = FullVsOn;
        clientPortMenuButtonCtrlStatus.enable = FullVsOn;
        clientPortMenuShowStatus.enable   = DSDDManON;
        clientPortMenuSelectStatus.enable = FullVsOn;
        if ~isempty(data.clientport)
            clientPortEditCtrlStatus.string = data.clientport;
            if ~isempty(dlgdata.swcPath)
                portPath = [swcRoot '/' dlgdata.swcPath '/Ports/' data.clientport];
            else
                portPath = [swcRoot '/' data.clientport];
            end
            [bExist, hDDObjPort] = dsdd('Exist', portPath, 'ObjectKind', 'ClientPort');
            if ~bExist
                [bExist, hDDObjPort] = dsdd('Exist', portPath, 'ObjectKind', 'ServerPort');
            end
            if bExist
                operationEditCtrlStatus.enable = FullVsOn;
                operationSelectButtonCtrlStatus.enable = FullVsOn;
                operationMenuButtonCtrlStatus.enable = FullVsOn;
                operationMenuShowStatus.enable   = DSDDManON;
                operationMenuSelectStatus.enable = FullVsOn;
                if ~isempty(data.operation)
                    operationEditCtrlStatus.string = data.operation;
                    interfaceRef = dsdd('GetClientServerInterfaceRef',hDDObjPort);
                    operationPath = [interfaceRoot '/' interfaceRef '/Operations/' data.operation];
                    bExist = dsdd('Exist', ...
                        operationPath, ...
                        'ObjectKind', 'Operation');
                    if ~bExist
                        operationEditCtrlStatus.iserror = 1;
                        statusString = 'Operation does not exist.';
                    end
                else
                    operationEditCtrlStatus.iserror = 1;
                    statusString = 'Operation does not exist.';
                end
            else
                clientPortEditCtrlStatus.iserror = 1;
                statusString = 'Client port does not exist.';
            end
        else
            clientPortEditCtrlStatus.iserror = 1;
            statusString = 'Client port does not exist.';
        end
    end
    if ~data.isrunnable && ~data.isoperationcall
        % disable SIL simulation checkbox, if no AUTOSAR is selected
        SILsimulationCheckboxCtrlStatus.enable = OFF;
    end
    SILsimulationCheckboxCtrlStatus.value = data.isimplementationforsilpil;
else
    isRunnableCheckboxCtrlStatus.enable = OFF;
    operationCheckboxCtrlStatus.enable = OFF;
    SILsimulationCheckboxCtrlStatus.enable = OFF;
end

FcnSaveCtrlUserData(Children, 'isRunnableCheckbox', isRunnableCheckboxCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'swcEdit', swcEditCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'swcSelectButton', swcSelectButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'swcMenuButton', swcMenuButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'runnableEdit', runnableEditCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'runnableSelectButton', runnableSelectButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'runnableMenuButton', runnableMenuButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'operationCallCheckbox', operationCheckboxCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'clientPortEdit', clientPortEditCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'clientPortSelectButton', clientPortSelectButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'clientPortMenuButton', clientPortMenuButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'operationEdit', operationEditCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'operationSelectButton', operationSelectButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'operationMenuButton', operationMenuButtonCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'descriptionText', descriptionTextCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'nameText', nameTextCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'classText', classTextCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'moduleText', moduleTextCtrlStatus, 0);
FcnSaveCtrlUserData(Children, 'showEventButton', showEventButtonCtrlStatus, 1);
FcnSaveCtrlUserData(Children, 'SILsimulationCheckbox', SILsimulationCheckboxCtrlStatus, 1);
FcnSaveCtrlUserData(swcMenu, 'show', swcMenuShowStatus, 0);
FcnSaveCtrlUserData(swcMenu, 'select', swcMenuSelectStatus, 0);
FcnSaveCtrlUserData(runnableMenu, 'show', runnableMenuShowStatus, 0);
FcnSaveCtrlUserData(runnableMenu, 'select', runnableMenuSelectStatus, 0);
FcnSaveCtrlUserData(clientPortMenu, 'show', clientPortMenuShowStatus, 0);
FcnSaveCtrlUserData(clientPortMenu, 'select', clientPortMenuSelectStatus, 0);
FcnSaveCtrlUserData(operationMenu, 'show', operationMenuShowStatus, 0);
FcnSaveCtrlUserData(operationMenu, 'select', operationMenuSelectStatus, 0);

% list of controls for which the status is set
ctrlsList = fieldnames(Children);
ctrlsList(strcmp(ctrlsList,'dualEditText')) = [];
ctrlsList = ctrlsList(cellfun('isempty', regexp(ctrlsList, 'Label', 'end')));
ctrlsList = ctrlsList(cellfun('isempty', regexp(ctrlsList, 'Groupbox', 'end')));

% Set status of controls
TLSetCtrlsStatus(dlgfig, Children, ctrlsList);
set(dlgdata.SystemButtons.StatusLabel, 'String', statusString);
% end of function FcnUpdateAutosarPage


%-----------------------------------------------------------------------------------------
% FcnSaveCtrlUserData saves UserData at controls
%
% INPUT ARGUMENTS
%   Children     Structure with controls
%   ctrl         Control for which the status is set
%   ctrlStatus   Status of this control
%   bInactive    0 if "inactive" status should be "off" instead
%
% OUTPUT ARGUMENTS
%   - / -
%-----------------------------------------------------------------------------------------
function FcnSaveCtrlUserData(Children, ctrl, ctrlStatus, bInactive)

% change state to string
if isfield(ctrlStatus, 'enable')
    enableState = ctrlStatus.enable;
    switch enableState
        case 0
            % off
            ctrlStatus.enable  = 'off';
        case 1
            % inactive
            if bInactive
                ctrlStatus.enable  = 'inactive';
            else
                ctrlStatus.enable  = 'off';
            end
        case 2
            % on
            ctrlStatus.enable  = 'on';
        otherwise
            error('Internal Error. Please contact TorstenPi!');
    end
end

% set status to control
if isfield(Children, ctrl)
    ctrl = Children.(ctrl);
    UserData = get(ctrl, 'UserData');
    UserData.ctrlStatus = ctrlStatus;
    set(ctrl, 'UserData', UserData);
end


%-------------------------------------------------------------------------------
% FcnChangeDefaultInput changes the string 'default' to '